├── .nvmrc ├── src ├── constants │ ├── env.ts │ ├── paths.ts │ └── http.ts ├── db │ ├── IFileDb.ts │ ├── bankAccounts.json │ └── bankAccountDatabase.ts ├── index.ts ├── utils │ ├── errors.ts │ ├── types.ts │ ├── modelManagerUtil.ts │ └── dataVerification.ts ├── controllers │ ├── api.controller.ts │ ├── auth.controller.ts │ └── connectedfields.controller.ts ├── validationSchemas │ ├── connectedfields.ts │ └── auth.ts ├── middleware │ └── checkValidationErrors.ts ├── models │ ├── auth.ts │ └── connectedfields.ts ├── dataModel │ └── model.cto ├── preStart.ts ├── env.ts ├── server.ts └── services │ ├── auth.service.ts │ └── connectedfields.ts ├── Account Registration Form - DocuCo.pdf ├── .prettierrc ├── jest.config.js ├── example.development.env ├── views └── index.pug ├── example.settings.txt ├── public └── js │ └── redirect.js ├── LICENSE ├── Containerfile ├── Dockerfile ├── package.json ├── .gitignore ├── maestro-checkpoint ├── web-form-config.json ├── workflow-definition.json └── esign-template.json ├── manifest.json ├── tsconfig.json ├── post-workshop-resources └── postWorkshopserver.js ├── server.js └── README.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 18.16.1 -------------------------------------------------------------------------------- /src/constants/env.ts: -------------------------------------------------------------------------------- 1 | export enum NodeEnvs { 2 | Dev = 'development', 3 | Test = 'test', 4 | Production = 'production', 5 | } 6 | -------------------------------------------------------------------------------- /Account Registration Form - DocuCo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docusign/docusign-discover-workshop-1/main/Account Registration Form - DocuCo.pdf -------------------------------------------------------------------------------- /src/db/IFileDb.ts: -------------------------------------------------------------------------------- 1 | interface IFileDb { 2 | csvFilePath: string; 3 | 4 | read(): T[]; 5 | findRecord(identifier: keyof T, value: string): T | undefined; 6 | } -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 150, 3 | "tabWidth": 2, 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "semi": true, 7 | "arrowParens": "avoid" 8 | } 9 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest').JestConfigWithTsJest} **/ 2 | module.exports = { 3 | testEnvironment: "node", 4 | transform: { 5 | "^.+.tsx?$": ["ts-jest",{}], 6 | }, 7 | }; -------------------------------------------------------------------------------- /example.development.env: -------------------------------------------------------------------------------- 1 | ## THIS IS A TEMPLATE FILE ## 2 | ## COPY BELOW CONTENT TO development.env ## 3 | 4 | NODE_ENV=development 5 | JWT_SECRET_KEY=1aed... 6 | OAUTH_CLIENT_ID=6f22... 7 | OAUTH_CLIENT_SECRET=29av... 8 | AUTHORIZATION_CODE=7905... 9 | PORT=3000 10 | -------------------------------------------------------------------------------- /views/index.pug: -------------------------------------------------------------------------------- 1 | html 2 | head 3 | title Redirect Page 4 | script(src=scriptPath) 5 | 6 | body 7 | h1 Welcome to the Redirect Page 8 | 9 | button(id="consentButton", data-redirect-uri=redirectUri, data-code=code, data-state=state) Click me to consent 10 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import './preStart'; // Must be the first import 2 | 3 | import env from './env'; 4 | import server from './server'; 5 | 6 | const SERVER_START_MSG = 'Express server started on port: ' + env.PORT.toString(); 7 | 8 | server.listen(env.PORT, () => console.info(SERVER_START_MSG)); 9 | -------------------------------------------------------------------------------- /example.settings.txt: -------------------------------------------------------------------------------- 1 | DS_CLIENT_ID=YOUR_INTEGRATION_KEY 2 | DS_CLIENT_SECRET=YOUR_SECRET 3 | DS_REDIRECT_URI=http://localhost:4000/callback 4 | DS_ACCOUNT_ID=YOUR_ACCOUNT_ID 5 | DS_AUTH_SERVER=https://account-d.docusign.com 6 | DS_API_BASE_PATH=https://api-d.docusign.com/v1 7 | MAESTRO_WORKFLOW_ID=YOUR_WORKFLOW_ID 8 | PORT=4000 9 | SESSION_SECRET=discover -------------------------------------------------------------------------------- /src/utils/errors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Miscellaneous shared classes go here. 3 | */ 4 | 5 | import HttpStatusCodes from '../constants/http'; 6 | 7 | /** 8 | * Error with status code and message 9 | */ 10 | export class RouteError extends Error { 11 | status: HttpStatusCodes; 12 | constructor(status: HttpStatusCodes, message: string) { 13 | super(message); 14 | this.status = status; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/controllers/api.controller.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | import Paths from '../constants/paths'; 3 | import authRouter from './auth.controller'; 4 | import connectedFieldsRouter from './connectedfields.controller'; 5 | 6 | const apiRouter = Router(); 7 | 8 | apiRouter.use(Paths.ConnectedFields.Base, connectedFieldsRouter); 9 | 10 | apiRouter.use(Paths.Auth.Base, authRouter); 11 | 12 | export default apiRouter; 13 | -------------------------------------------------------------------------------- /src/utils/types.ts: -------------------------------------------------------------------------------- 1 | import * as e from 'express'; 2 | import { Query } from 'express-serve-static-core'; 3 | 4 | export interface IReq extends e.Request { 5 | body: T; 6 | } 7 | 8 | export interface IReqQuery extends e.Request { 9 | query: T; 10 | body: U; 11 | } 12 | 13 | export interface IRes extends e.Response {} 14 | 15 | export type Immutable = { 16 | readonly [K in keyof T]: Immutable; 17 | }; 18 | -------------------------------------------------------------------------------- /src/validationSchemas/connectedfields.ts: -------------------------------------------------------------------------------- 1 | import { Schema } from 'express-validator'; 2 | 3 | export const connectedFieldsGetTypeNamesRecordBody: Schema = {}; 4 | 5 | export const connectedFieldsGetTypeDefinitionsRecordBody: Schema = { 6 | typeNames: { isArray: true } 7 | } 8 | 9 | export const connectedFieldsVerifyBody: Schema = { 10 | typeName: { isString: true }, 11 | idempotencyKey: { isString: true }, 12 | data: { isObject: true } 13 | } -------------------------------------------------------------------------------- /src/validationSchemas/auth.ts: -------------------------------------------------------------------------------- 1 | import { Schema } from 'express-validator'; 2 | import env from '../env'; 3 | 4 | export const authorizeQuery: Schema = { 5 | redirect_uri: { trim: true, isURL: true }, 6 | client_id: { trim: true, equals: { options: env.OAUTH_CLIENT_ID } }, 7 | state: { trim: true, isString: true }, 8 | }; 9 | 10 | export const generateAuthTokenBody: Schema = { 11 | grant_type: { isIn: { options: [['authorization_code', 'refresh_token', 'client_credentials']] } }, 12 | }; 13 | -------------------------------------------------------------------------------- /src/middleware/checkValidationErrors.ts: -------------------------------------------------------------------------------- 1 | import { validationResult } from 'express-validator'; 2 | import { IReq, IRes } from '../utils/types'; 3 | import { NextFunction } from 'express'; 4 | import HttpStatusCodes from '../constants/http'; 5 | 6 | export default (req: IReq, res: IRes, next: NextFunction) => { 7 | const errors = validationResult(req); 8 | if (!errors.isEmpty()) { 9 | return res.status(HttpStatusCodes.BAD_REQUEST).json({ errors: errors.array() }); 10 | } 11 | return next(); 12 | }; 13 | -------------------------------------------------------------------------------- /src/models/auth.ts: -------------------------------------------------------------------------------- 1 | import { Query } from 'express-serve-static-core'; 2 | 3 | export interface AuthorizeQuery extends Query { 4 | redirect_uri: string; 5 | client_id: string; 6 | state: string; 7 | } 8 | 9 | export type GenerateAuthTokenBody = 10 | | { 11 | code?: string; 12 | grant_type: 'authorization_code'; 13 | } 14 | | { 15 | refresh_token?: string; 16 | grant_type: 'refresh_token'; 17 | } 18 | | { 19 | client_id?: string; 20 | client_secret?: string; 21 | grant_type: 'client_credentials'; 22 | }; -------------------------------------------------------------------------------- /src/constants/paths.ts: -------------------------------------------------------------------------------- 1 | import { Immutable } from '../utils/types'; 2 | 3 | const paths = { 4 | Base: '/api', 5 | ConnectedFields: { 6 | Base: '/connectedfields', 7 | Verify: { 8 | Post: '/verify', 9 | }, 10 | GetTypeNames: { 11 | Post: '/getTypeNames', 12 | }, 13 | GetTypeDefinitions: { 14 | Post: '/getTypeDefinitions', 15 | } 16 | }, 17 | Auth: { 18 | Base: '/oauth', 19 | Authorize: { 20 | Get: '/authorize', 21 | }, 22 | Token: { 23 | Post: '/token', 24 | }, 25 | UserInfo: { 26 | Get: '/userinfo', 27 | }, 28 | }, 29 | }; 30 | 31 | export type TPaths = Immutable; 32 | export default paths as TPaths; 33 | -------------------------------------------------------------------------------- /public/js/redirect.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | document.addEventListener('DOMContentLoaded', () => { 3 | const consentButton = document.getElementById('consentButton'); 4 | if (!consentButton) { 5 | console.error('Consent button not found'); 6 | return; 7 | } 8 | consentButton.addEventListener('click', () => { 9 | const redirectUri = consentButton.dataset.redirectUri; 10 | const code = consentButton.dataset.code; 11 | const state = consentButton.dataset.state; 12 | if (!redirectUri || !code || !state) { 13 | console.error('Missing redirect parameters'); 14 | return; 15 | } 16 | window.location.href = `${redirectUri}?code=${code}&state=${state}`; 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/dataModel/model.cto: -------------------------------------------------------------------------------- 1 | namespace org.example@1.0.0 2 | 3 | @VerifiableType 4 | @Term("Account Type") 5 | enum AccountType { 6 | @Term("Checking") o checking 7 | @Term("Savings") o savings 8 | } 9 | 10 | @VerifiableType 11 | @Term("Bank Account Opening") 12 | concept BankAccountOpening { 13 | @IsRequiredForVerifyingType 14 | @Term("Routing Number") 15 | o String routingNumber regex=/^\d{9}$/ 16 | 17 | @IsRequiredForVerifyingType 18 | @Term("Account Number") 19 | o String accountNumber regex=/^[0-9a-zA-Z]+$/ 20 | 21 | @IsRequiredForVerifyingType 22 | @Term("Account Holder Name") 23 | o String accountHolderName 24 | 25 | @IsRequiredForVerifyingType 26 | @Term("Bank Name") 27 | o String bankName 28 | 29 | @Term("Status") 30 | o String status optional 31 | } 32 | -------------------------------------------------------------------------------- /src/preStart.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Pre-start is where we want to place things that must run BEFORE the express 3 | * server is started. This is useful for environment variables, command-line 4 | * arguments, and cron-jobs. 5 | */ 6 | 7 | // NOTE: DO NOT IMPORT ANY SOURCE CODE HERE 8 | import path from 'path'; 9 | import dotenv from 'dotenv'; 10 | import { parse } from 'ts-command-line-args'; 11 | 12 | // **** Types **** // 13 | 14 | interface IArgs { 15 | env: string; 16 | } 17 | 18 | // **** Setup **** // 19 | 20 | // Command line arguments 21 | const args = parse({ 22 | env: { 23 | type: String, 24 | defaultValue: 'development', 25 | alias: 'e', 26 | }, 27 | }); 28 | 29 | // Set the env file 30 | const result2 = dotenv.config({ 31 | path: path.join(__dirname, `../${args.env}.env`), 32 | }); 33 | if (result2.error) { 34 | throw result2.error; 35 | } 36 | -------------------------------------------------------------------------------- /src/utils/modelManagerUtil.ts: -------------------------------------------------------------------------------- 1 | import { ModelManager } from "@accordproject/concerto-core"; 2 | import path from "path"; 3 | import fs from 'fs'; 4 | 5 | export class ModelManagerUtil { 6 | /** 7 | * Create a ModelManager instance from a CTO file. 8 | * @param {string} ctoFile - the path to the CTO file. 9 | * @return {ModelManager} a ModelManager instance. 10 | */ 11 | public static createModelManagerFromCTO(ctoFile: string): ModelManager { 12 | // Needed as this is a workaround to skip line locations in generated AST 13 | // @ts-ignore 14 | const modelManager: ModelManager = new ModelManager({ strict: true, skipLocationNodes: true }); 15 | modelManager.addCTOModel(fs.readFileSync(path.join(__dirname, "../dataModel/model.cto"),'utf8')); 16 | modelManager.validateModelFiles(); 17 | return modelManager 18 | } 19 | } -------------------------------------------------------------------------------- /src/controllers/auth.controller.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | 3 | import Paths from '../constants/paths'; 4 | import { authorize, generateAuthToken, getUserInfo } from '../services/auth.service'; 5 | import { expressjwt as jwt } from 'express-jwt'; 6 | import env from '../env'; 7 | import { checkSchema } from 'express-validator'; 8 | import { authorizeQuery } from '../validationSchemas/auth'; 9 | import checkValidationErrors from '../middleware/checkValidationErrors'; 10 | 11 | const authRouter = Router(); 12 | 13 | authRouter.get(Paths.Auth.Authorize.Get, checkSchema(authorizeQuery, ['query']), checkValidationErrors, authorize); 14 | 15 | authRouter.post(Paths.Auth.Token.Post, generateAuthToken); 16 | 17 | authRouter.get( 18 | Paths.Auth.UserInfo.Get, 19 | jwt({ 20 | secret: env.JWT_SECRET_KEY, 21 | algorithms: ['HS256'], 22 | }), 23 | getUserInfo, 24 | ); 25 | 26 | export default authRouter; 27 | -------------------------------------------------------------------------------- /src/env.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Environments variables declared here. 3 | */ 4 | 5 | /* eslint-disable node/no-process-env */ 6 | 7 | const { NODE_ENV, PORT, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, AUTHORIZATION_CODE, JWT_SECRET_KEY } = process.env; 8 | 9 | if (!NODE_ENV) { 10 | throw new Error('NODE_ENV not set'); 11 | } 12 | 13 | if (!PORT) { 14 | throw new Error('PORT not set'); 15 | } 16 | 17 | if (!OAUTH_CLIENT_ID) { 18 | throw new Error('OAUTH_CLIENT_ID not set'); 19 | } 20 | 21 | if (!OAUTH_CLIENT_SECRET) { 22 | throw new Error('OAUTH_CLIENT_SECRET not set'); 23 | } 24 | 25 | if (!AUTHORIZATION_CODE) { 26 | throw new Error('AUTHORIZATION_CODE not set'); 27 | } 28 | 29 | if (!JWT_SECRET_KEY) { 30 | throw new Error('JWT_SECRET_KEY not set'); 31 | } 32 | 33 | export default { 34 | NODE_ENV, 35 | PORT, 36 | OAUTH_CLIENT_ID, 37 | OAUTH_CLIENT_SECRET, 38 | AUTHORIZATION_CODE, 39 | JWT_SECRET_KEY, 40 | }; 41 | -------------------------------------------------------------------------------- /src/db/bankAccounts.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "1", 4 | "routingNumber": "111000025", 5 | "accountNumber": "1234567890", 6 | "accountType": "checking", 7 | "accountHolderName": "John Doe", 8 | "bankName": "Bank of America", 9 | "status": "active" 10 | }, 11 | { 12 | "id": "2", 13 | "routingNumber": "222000111", 14 | "accountNumber": "9876543210", 15 | "accountType": "savings", 16 | "accountHolderName": "Jane Smith", 17 | "bankName": "Chase Bank", 18 | "status": "blocked" 19 | }, 20 | { 21 | "id": "3", 22 | "routingNumber": "333123456", 23 | "accountNumber": "5556667777", 24 | "accountType": "checking", 25 | "accountHolderName": "Robert Brown", 26 | "bankName": "Wells Fargo", 27 | "status": "existing" 28 | }, 29 | { 30 | "id": "4", 31 | "routingNumber": "444987654", 32 | "accountNumber": "1122334455", 33 | "accountType": "checking", 34 | "accountHolderName": "Emily Johnson", 35 | "bankName": "CitiBank", 36 | "status": "active" 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Docusign Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/utils/dataVerification.ts: -------------------------------------------------------------------------------- 1 | import { 2 | findByOpeningFull, 3 | findByRoutingAccount, 4 | BankAccountRecord, 5 | } from "../db/bankAccountDatabase"; 6 | 7 | const ok = () => ({ matched: true } as const); 8 | const fail = (message: string) => ({ matched: false as const, message }); 9 | 10 | export const verifyBankAccountOpening = (data: { 11 | routingNumber?: string; 12 | accountNumber?: string; 13 | accountHolderName?: string; 14 | bankName?: string; 15 | status?: string; 16 | }) => { 17 | const routingNumber = data?.routingNumber?.trim(); 18 | const accountNumber = data?.accountNumber?.trim(); 19 | const accountHolderName = data?.accountHolderName?.trim(); 20 | const bankName = data?.bankName?.trim(); 21 | 22 | if (!routingNumber || !accountNumber || !accountHolderName || !bankName) { 23 | return fail("Missing one or more required fields: routingNumber, accountNumber, accountHolderName, bankName"); 24 | } 25 | 26 | let record: BankAccountRecord | undefined = findByOpeningFull( 27 | routingNumber, 28 | accountNumber, 29 | accountHolderName, 30 | bankName 31 | ); 32 | 33 | if (!record) { 34 | record = findByRoutingAccount(routingNumber, accountNumber); 35 | } 36 | 37 | if (!record) return fail("No matching bank account record found"); 38 | 39 | if (record.status === "blocked") return fail("This account is blocked"); 40 | if (record.status === "existing") return fail("This account already exists"); 41 | 42 | return ok(); 43 | }; 44 | -------------------------------------------------------------------------------- /Containerfile: -------------------------------------------------------------------------------- 1 | # Global arguments 2 | ARG BASE_IMAGE=node:lts-alpine 3 | ARG APP_DIR=/usr/src/app 4 | ARG UID=1000 5 | ARG GID=1000 6 | ARG PORT=3000 7 | 8 | # Base stage 9 | FROM ${BASE_IMAGE} AS base 10 | ARG APP_DIR 11 | ARG UID 12 | ARG GID 13 | ARG PORT 14 | 15 | RUN mkdir -p ${APP_DIR} && \ 16 | chown -R ${UID}:${GID} ${APP_DIR} 17 | 18 | USER ${UID}:${GID} 19 | 20 | WORKDIR ${APP_DIR} 21 | 22 | ENV PORT=${PORT} 23 | EXPOSE ${PORT} 24 | 25 | COPY --chown=${UID}:${GID} package.json . 26 | 27 | # Dependencies stage 28 | FROM base AS dependencies 29 | ARG APP_DIR 30 | 31 | RUN npm install && \ 32 | npm cache clean --force && \ 33 | touch ${APP_DIR}/production.env && \ 34 | touch ${APP_DIR}/development.env 35 | 36 | ENV PATH=${APP_DIR}/node_modules/.bin:$PATH 37 | 38 | # Development stage 39 | FROM dependencies AS development 40 | ARG UID 41 | ARG GID 42 | 43 | ENV NODE_ENV=development 44 | 45 | COPY --chown=${UID}:${GID} . . 46 | 47 | CMD ["npm", "run", "dev"] 48 | 49 | # Build stage 50 | FROM dependencies AS build 51 | ARG UID 52 | ARG GID 53 | 54 | COPY --chown=${UID}:${GID} . . 55 | 56 | RUN npm run build 57 | 58 | # Production stage 59 | FROM dependencies AS production 60 | ARG UID 61 | ARG GID 62 | ARG APP_DIR 63 | 64 | ENV NODE_ENV=production 65 | 66 | COPY --chown=${UID}:${GID} ./public ./public 67 | COPY --chown=${UID}:${GID} ./views ./views 68 | COPY --chown=${UID}:${GID} --from=build ${APP_DIR}/dist ./dist 69 | 70 | CMD ["node", "./dist", "--env=production"] 71 | -------------------------------------------------------------------------------- /src/controllers/connectedfields.controller.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | 3 | import Paths from '../constants/paths'; 4 | import { expressjwt as jwt } from 'express-jwt'; 5 | import { checkSchema } from 'express-validator'; 6 | import checkValidationErrors from '../middleware/checkValidationErrors'; 7 | import env from '../env'; 8 | import { 9 | connectedFieldsGetTypeDefinitionsRecordBody, 10 | connectedFieldsGetTypeNamesRecordBody, 11 | connectedFieldsVerifyBody, 12 | } from '../validationSchemas/connectedfields'; 13 | import { getTypeDefinitions, getTypeNames, verify } from '../services/connectedfields'; 14 | 15 | const connectedFieldsRouter = Router(); 16 | 17 | connectedFieldsRouter.post( 18 | Paths.ConnectedFields.GetTypeNames.Post, 19 | jwt({ 20 | secret: env.JWT_SECRET_KEY, 21 | algorithms: ['HS256'], 22 | }), 23 | checkSchema(connectedFieldsGetTypeNamesRecordBody, ['body']), 24 | checkValidationErrors, 25 | getTypeNames, 26 | ); 27 | 28 | connectedFieldsRouter.post( 29 | Paths.ConnectedFields.GetTypeDefinitions.Post, 30 | jwt({ 31 | secret: env.JWT_SECRET_KEY, 32 | algorithms: ['HS256'], 33 | }), 34 | checkSchema(connectedFieldsGetTypeDefinitionsRecordBody, ['body']), 35 | checkValidationErrors, 36 | getTypeDefinitions, 37 | ); 38 | 39 | connectedFieldsRouter.post( 40 | Paths.ConnectedFields.Verify.Post, 41 | jwt({ 42 | secret: env.JWT_SECRET_KEY, 43 | algorithms: ['HS256'], 44 | }), 45 | checkSchema(connectedFieldsVerifyBody, ['body']), 46 | checkValidationErrors, 47 | verify, 48 | ); 49 | 50 | export default connectedFieldsRouter; 51 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Global arguments 2 | ARG BASE_IMAGE=node:lts-alpine 3 | ARG APP_DIR=/usr/src/app 4 | ARG UID=1000 5 | ARG GID=1000 6 | ARG PORT=3000 7 | 8 | # Base stage 9 | FROM ${BASE_IMAGE} AS base 10 | ARG APP_DIR 11 | ARG UID 12 | ARG GID 13 | ARG PORT 14 | 15 | RUN mkdir -p ${APP_DIR} && \ 16 | chown -R ${UID}:${GID} ${APP_DIR} 17 | 18 | USER ${UID}:${GID} 19 | 20 | WORKDIR ${APP_DIR} 21 | 22 | ENV PORT=${PORT} 23 | EXPOSE ${PORT} 24 | 25 | # Dependencies stage 26 | FROM base AS dependencies 27 | ARG APP_DIR 28 | 29 | RUN --mount=type=bind,source=./package.json,target=${APP_DIR}/package.json \ 30 | --mount=type=cache,target=${APP_DIR}/.npm,uid=$UID,gid=$GID,mode=0755,sharing=locked \ 31 | npm install && \ 32 | touch ${APP_DIR}/production.env && \ 33 | touch ${APP_DIR}/development.env 34 | 35 | ENV PATH=${APP_DIR}/node_modules/.bin:$PATH 36 | 37 | # Development stage 38 | FROM dependencies AS development 39 | ARG UID 40 | ARG GID 41 | 42 | ENV NODE_ENV=development 43 | 44 | COPY --chown=${UID}:${GID} . . 45 | 46 | CMD ["npm", "run", "dev"] 47 | 48 | # Build stage 49 | FROM dependencies AS build 50 | ARG UID 51 | ARG GID 52 | 53 | COPY --chown=${UID}:${GID} . . 54 | 55 | RUN npm run build 56 | 57 | # Production stage 58 | FROM dependencies AS production 59 | ARG UID 60 | ARG GID 61 | ARG APP_DIR 62 | 63 | ENV NODE_ENV=production 64 | 65 | COPY --chown=${UID}:${GID} package.json . 66 | COPY --chown=${UID}:${GID} ./public ./public 67 | COPY --chown=${UID}:${GID} ./views ./views 68 | COPY --chown=${UID}:${GID} --from=build ${APP_DIR}/dist ./dist 69 | 70 | CMD ["node", "./dist", "--env=production"] 71 | -------------------------------------------------------------------------------- /src/server.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Setup express server. 3 | */ 4 | 5 | import morgan from 'morgan'; 6 | import helmet from 'helmet'; 7 | import express, { Request, Response, NextFunction } from 'express'; 8 | 9 | import 'express-async-errors'; 10 | 11 | import BaseRouter from './controllers/api.controller'; 12 | import Paths from './constants/paths'; 13 | 14 | import env from './env'; 15 | import HttpStatusCodes from './constants/http'; 16 | 17 | import { NodeEnvs } from './constants/env'; 18 | import { RouteError } from './utils/errors'; 19 | import { UnauthorizedError } from 'express-jwt'; 20 | import path from 'path'; 21 | 22 | const app = express(); 23 | 24 | app.set('view engine', 'pug'); 25 | app.set('views', './views'); 26 | 27 | app.use(express.json({ limit: '50mb' })); 28 | app.use(express.urlencoded({ extended: true })); 29 | 30 | app.use('/js', express.static(path.join(__dirname, '../public/js'))); 31 | 32 | // Show routes called in console during development 33 | if (env.NODE_ENV === NodeEnvs.Dev) { 34 | app.use(morgan('dev')); 35 | } 36 | 37 | // Security 38 | if (env.NODE_ENV === NodeEnvs.Production) { 39 | app.use(helmet()); 40 | } 41 | 42 | // Add APIs, must be after middleware 43 | app.use(Paths.Base, BaseRouter); 44 | 45 | // Add error handler 46 | app.use((err: Error, _: Request, res: Response, next: NextFunction) => { 47 | if (env.NODE_ENV !== NodeEnvs.Test) { 48 | console.error(err, true); 49 | } 50 | let status = HttpStatusCodes.BAD_REQUEST; 51 | if (err instanceof RouteError || err instanceof UnauthorizedError) { 52 | status = err.status; 53 | } 54 | return res.status(status).json({ error: err.message }); 55 | }); 56 | 57 | export default app; 58 | -------------------------------------------------------------------------------- /src/db/bankAccountDatabase.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | 4 | export type AccountType = "checking" | "savings"; 5 | 6 | export interface BankAccountRecord { 7 | id: string; 8 | routingNumber: string; 9 | accountNumber: string; 10 | accountType: AccountType; 11 | accountHolderName: string; 12 | bankName: string; 13 | status?: "active" | "blocked" | "existing"; 14 | } 15 | 16 | const JSON_PATH = path.join(__dirname, "bankAccounts.json"); 17 | 18 | let bankAccounts: BankAccountRecord[] = []; 19 | 20 | (function load() { 21 | try { 22 | const raw = fs.readFileSync(JSON_PATH, "utf-8"); 23 | bankAccounts = JSON.parse(raw) as BankAccountRecord[]; 24 | } catch (err) { 25 | console.error("Failed to load bankAccounts.json:", err); 26 | bankAccounts = []; 27 | } 28 | })(); 29 | 30 | export const getBankAccounts = (): BankAccountRecord[] => bankAccounts; 31 | 32 | export const findByRoutingAccount = ( 33 | routingNumber: string, 34 | accountNumber: string 35 | ): BankAccountRecord | undefined => { 36 | return bankAccounts.find( 37 | (rec) => 38 | rec.routingNumber === routingNumber && rec.accountNumber === accountNumber 39 | ); 40 | }; 41 | 42 | export const findByOpeningFull = ( 43 | routingNumber: string, 44 | accountNumber: string, 45 | accountHolderName: string, 46 | bankName: string 47 | ): BankAccountRecord | undefined => { 48 | return bankAccounts.find( 49 | (rec) => 50 | rec.routingNumber === routingNumber && 51 | rec.accountNumber === accountNumber && 52 | rec.accountHolderName.toLowerCase().trim() === 53 | accountHolderName.toLowerCase().trim() && 54 | rec.bankName.toLowerCase().trim() === bankName.toLowerCase().trim() 55 | ); 56 | }; 57 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "discover-workshop-bank-draft", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "build": "tsc --build tsconfig.json && npm run copy-files", 6 | "copy-files": "cpx './src/**/*.cto' 'dist' && cpx './src/db/*.csv' 'dist/db'", 7 | "lint": "npx eslint --ext .ts src/", 8 | "start": "node ./dist --env=production", 9 | "dev": "nodemon", 10 | "trigger": "node server.js" 11 | }, 12 | "nodemonConfig": { 13 | "watch": [ 14 | "src", 15 | "views" 16 | ], 17 | "ext": "ts, pug", 18 | "exec": "./node_modules/.bin/ts-node --files -r tsconfig-paths/register ./src" 19 | }, 20 | "dependencies": { 21 | "@docusign/iam-sdk": "^1.0.0-beta.3", 22 | "@accordproject/concerto-cli": "^3.16.6", 23 | "@accordproject/concerto-core": "~3.19.6", 24 | "@accordproject/concerto-types": "~3.19.6", 25 | "ajv": "^8.17.1", 26 | "csv-parse": "^5.6.0", 27 | "dotenv": "^16.0.3", 28 | "express": "^4.18.2", 29 | "express-session": "^1.17.3", 30 | "express-async-errors": "^3.1.1", 31 | "express-jwt": "^8.4.1", 32 | "express-validator": "^7.0.1", 33 | "helmet": "^7.0.0", 34 | "install": "^0.13.0", 35 | "jsonwebtoken": "^9.0.0", 36 | "moment": "^2.30.1", 37 | "morgan": "^1.10.0", 38 | "npm": "^11.0.0", 39 | "pug": "^3.0.2", 40 | "ts-command-line-args": "^2.5.0", 41 | "ts-force": "^3.4.3" 42 | }, 43 | "devDependencies": { 44 | "@types/express": "^4.17.21", 45 | "@types/jest": "^29.5.14", 46 | "@types/jsonwebtoken": "^9.0.2", 47 | "@types/morgan": "^1.9.4", 48 | "@types/node": "^20.2.3", 49 | "@types/pug": "^2.0.8", 50 | "@typescript-eslint/eslint-plugin": "^5.59.7", 51 | "@typescript-eslint/parser": "^5.59.7", 52 | "cpx": "^1.5.0", 53 | "eslint": "^8.41.0", 54 | "eslint-plugin-node": "^11.1.0", 55 | "jest": "^29.7.0", 56 | "nodemon": "^2.0.22", 57 | "ts-jest": "^29.2.5", 58 | "ts-node": "^10.9.1", 59 | "tsconfig-paths": "^4.2.0", 60 | "typescript": "^5.7.3" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | development.env 82 | production.env 83 | 84 | # parcel-bundler cache (https://parceljs.org/) 85 | .cache 86 | .parcel-cache 87 | 88 | # Next.js build output 89 | .next 90 | out 91 | 92 | # Nuxt.js build / generate output 93 | .nuxt 94 | dist 95 | 96 | # Gatsby files 97 | .cache/ 98 | # Comment in the public line in if your project uses Gatsby and not Next.js 99 | # https://nextjs.org/blog/next-9-1#public-directory-support 100 | # public 101 | 102 | # vuepress build output 103 | .vuepress/dist 104 | 105 | # vuepress v2.x temp and cache directory 106 | .temp 107 | .cache 108 | 109 | # Docusaurus cache and generated files 110 | .docusaurus 111 | 112 | # Serverless directories 113 | .serverless/ 114 | 115 | # FuseBox cache 116 | .fusebox/ 117 | 118 | # DynamoDB Local files 119 | .dynamodb/ 120 | 121 | # TernJS port file 122 | .tern-port 123 | 124 | # Stores VSCode versions used for testing VSCode extensions 125 | .vscode-test 126 | 127 | # yarn v2 128 | .yarn/cache 129 | .yarn/unplugged 130 | .yarn/build-state.yml 131 | .yarn/install-state.gz 132 | .pnp.* 133 | 134 | .DS_Store 135 | 136 | package-lock.json -------------------------------------------------------------------------------- /src/services/auth.service.ts: -------------------------------------------------------------------------------- 1 | import { IReq, IReqQuery, IRes } from '../utils/types'; 2 | import jwt from 'jsonwebtoken'; 3 | import { JwtPayload } from 'jsonwebtoken'; 4 | import { AuthorizeQuery, GenerateAuthTokenBody } from '../models/auth'; 5 | import env from '../env'; 6 | import crypto from 'crypto'; 7 | import { error } from 'console'; 8 | 9 | export const authorize = (req: IReqQuery, res: IRes) => { 10 | const { 11 | query: { redirect_uri: redirectUri, state }, 12 | } = req; 13 | 14 | // Determine the script path dynamically based on the environment 15 | const scriptPath = '/js/redirect.js' 16 | 17 | return res.render('index.pug', { 18 | redirectUri, 19 | code: env.AUTHORIZATION_CODE, 20 | state, 21 | scriptPath, // Pass the script path to the Pug template 22 | }); 23 | }; 24 | 25 | export const generateAuthToken = (req: IReq, res: IRes) => { 26 | const accessToken = jwt.sign({ type: 'access_token', sub: crypto.randomUUID(), email: `${crypto.randomUUID()}@test.com` }, env.JWT_SECRET_KEY, { 27 | expiresIn: 3600, 28 | }); 29 | 30 | const refreshToken = jwt.sign({ type: 'refresh_token' }, env.JWT_SECRET_KEY); 31 | 32 | const jwtResponse = { 33 | access_token: accessToken, 34 | token_type: 'Bearer', 35 | expires_in: 3600, 36 | refresh_token: refreshToken, 37 | }; 38 | 39 | if ( 40 | req.body.grant_type === 'authorization_code' && 41 | typeof req.body.code === 'string' && 42 | decodeURIComponent(req.body.code.replace(/\+/g, '%20')) === env.AUTHORIZATION_CODE 43 | ) { 44 | return res.json(jwtResponse); 45 | } else if (req.body.grant_type === 'refresh_token' && req.body.refresh_token) { 46 | const payload = jwt.verify(req.body.refresh_token, env.JWT_SECRET_KEY) as JwtPayload; 47 | if (payload.type !== 'refresh_token') { 48 | throw new Error(); 49 | } 50 | return res.json(jwtResponse); 51 | } else if(req.body.grant_type === 'client_credentials') { 52 | 53 | const authHeader = req.headers.authorization; 54 | 55 | if(!authHeader?.startsWith('Basic ')){ 56 | throw new Error(); 57 | } 58 | 59 | const base64Credentials = authHeader.split(' ')[1]; 60 | const decoded = Buffer.from(base64Credentials, 'base64').toString('utf-8'); 61 | const [clientId, clientSecret] = decoded.split(':'); 62 | 63 | const decodedClientId = decodeURIComponent(clientId.replace(/\+/g, '%20')); 64 | const decodedClientSecret = decodeURIComponent(clientSecret.replace(/\+/g, '%20')); 65 | 66 | if(decodedClientId === env.OAUTH_CLIENT_ID && decodedClientSecret === env.OAUTH_CLIENT_SECRET){ 67 | return res.json(jwtResponse); 68 | } else { 69 | throw new Error(); 70 | } 71 | } 72 | 73 | throw new Error(JSON.stringify(req.body)); 74 | }; 75 | 76 | export const getUserInfo = (req: IReq, res: IRes) => { 77 | const token = req.headers.authorization?.split(' ')[1]; 78 | if (!token) { 79 | throw new Error(); 80 | } 81 | const payload = jwt.verify(token, env.JWT_SECRET_KEY) as JwtPayload; 82 | 83 | if (!payload) { 84 | throw new Error('Invalid token'); 85 | } 86 | 87 | return res.json({ sub: payload.sub, email: payload.email as string }); 88 | }; 89 | -------------------------------------------------------------------------------- /maestro-checkpoint/web-form-config.json: -------------------------------------------------------------------------------- 1 | {"id":"237187be-c204-450a-a3e1-b6bca91305d5","accountId":"b0f5ebb5-07a7-4aed-836f-7009793c445d","isPublished":true,"isEnabled":true,"hasDraftChanges":true,"formState":"active","formProperties":{"name":"Bank Account Details","isPrivateAccess":false,"allowSending":false,"unsupportedSendingReason":"standalone"},"formMetadata":{"source":"blank","createdDateTime":"2025-10-20T18:25:38.681Z","publishedSlug":"df37db5b63b5157049189fdb760261a6","owner":{"userId":"c47f9df9-8cc1-468d-ba9b-0ef93d7e6dfc","userName":"Rob"},"lastModifiedDateTime":"2025-10-27T02:25:44.015Z","lastModifiedBy":{"userId":"c47f9df9-8cc1-468d-ba9b-0ef93d7e6dfc","userName":"Rob"},"publishedComponentNames":{"email":"TextBox","accountHolderName":"TextBox","bankName":"TextBox","accountNumber":"TextBox","routingNumber":"TextBox"},"admModelNamespace":"docusign.forms._b0f5ebb5_07a7_4aed_836f_7009793c445d._237187be_c204_450a_a3e1_b6bca91305d5","formContentModifiedBy":{"userId":"c47f9df9-8cc1-468d-ba9b-0ef93d7e6dfc","userName":"Rob"},"formContentModifiedDateTime":"2025-10-26T22:54:13.183Z","admModelVersion":"1.1.0","type":"standalone","formPropertiesModifiedBy":{"userId":"c47f9df9-8cc1-468d-ba9b-0ef93d7e6dfc","userName":"Rob"},"formPropertiesModifiedDateTime":"2025-10-20T18:26:41.238Z","lastPublishedBy":{"userId":"c47f9df9-8cc1-468d-ba9b-0ef93d7e6dfc","userName":"Rob"},"lastPublishedDateTime":"2025-10-26T23:01:35.784Z","lastEnabledBy":{"userId":"c47f9df9-8cc1-468d-ba9b-0ef93d7e6dfc","userName":"Rob"},"lastEnabledDateTime":"2025-10-26T23:01:35.784Z"},"formContent":{"components":{"Root_Of_Journey":{"children":["Welcome_EsaBVMPg","Step_BhhqWEx6","Summary_8jTiweSA","FormSubmitAction_wN4ZcesX","Thankyou_H6_AMmb2"],"text":"","componentKey":"Root_Of_Journey","componentType":"Root","componentName":"Root_Of_Journey","componentRules":{}},"Welcome_EsaBVMPg":{"startButtonText":"Start","subText":"Please fill out your bank information in this form.","text":"Bank Account Registration Details","componentKey":"Welcome_EsaBVMPg","componentType":"Welcome"},"Step_BhhqWEx6":{"children":["TextBox_InZ5Zatt","TextBox_e_GCqTE7","TextBox_D3oq0Sa_","TextBox_h88NqfFV","TextBox_MupRdVKQ"],"componentKey":"Step_BhhqWEx6","componentName":"Step_BhhqWEx6","componentType":"Step","text":"Bank Account Details"},"Summary_8jTiweSA":{"subText":"Please review the information you have entered:","text":"Summary","componentKey":"Summary_8jTiweSA","componentType":"Summary"},"FormSubmitAction_wN4ZcesX":{"componentKey":"FormSubmitAction_wN4ZcesX","componentType":"FormSubmitAction"},"Thankyou_H6_AMmb2":{"confirmationButtonText":"Done","confirmationButtonUrl":"","showConfirmationButton":false,"subText":"We've received your form.","text":"Thank you","componentKey":"Thankyou_H6_AMmb2","componentType":"Thankyou"},"TextBox_InZ5Zatt":{"label":"Email","maxLength":4000,"componentKey":"TextBox_InZ5Zatt","componentType":"TextBox","componentName":"email","required":true},"TextBox_e_GCqTE7":{"label":"Account Holder Name","maxLength":4000,"componentKey":"TextBox_e_GCqTE7","componentType":"TextBox","componentName":"accountHolderName","required":true},"TextBox_D3oq0Sa_":{"label":"Bank Name","maxLength":4000,"componentKey":"TextBox_D3oq0Sa_","componentType":"TextBox","componentName":"bankName","required":true},"TextBox_h88NqfFV":{"label":"Account Number","maxLength":4000,"componentKey":"TextBox_h88NqfFV","componentType":"TextBox","componentName":"accountNumber","required":true},"TextBox_MupRdVKQ":{"label":"Routing Number","maxLength":4000,"componentKey":"TextBox_MupRdVKQ","componentType":"TextBox","componentName":"routingNumber","required":true}},"isStandalone":true,"templates":[]},"formLocale":"en","versionId":2,"eSignTemplates":[]} -------------------------------------------------------------------------------- /src/services/connectedfields.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import { ConceptDeclaration, ModelManager } from "@accordproject/concerto-core"; 3 | import { IReq, IRes } from "../utils/types"; 4 | import { ModelManagerUtil } from "../utils/modelManagerUtil"; 5 | 6 | import { 7 | GetTypeDefinitionsResponse, 8 | TypeNameInfo, 9 | VerifyBody, 10 | VerifyResponse, 11 | } from "../models/connectedfields"; 12 | 13 | import { verifyBankAccountOpening } from "../utils/dataVerification"; 14 | 15 | enum ErrorCode { 16 | INTERNAL_ERROR = "INTERNAL_ERROR", 17 | NOT_FOUND = "NOT_FOUND", 18 | BAD_REQUEST = "BAD_REQUEST", 19 | } 20 | 21 | type ErrorResponse = { message: string; code: string }; 22 | 23 | const generateErrorResponse = (code: ErrorCode, message: unknown): ErrorResponse => ({ 24 | code, 25 | message: String(message), 26 | }); 27 | 28 | const MODEL_MANAGER: ModelManager = ModelManagerUtil.createModelManagerFromCTO( 29 | path.join(__dirname, "../dataModel/model.cto") 30 | ); 31 | const MODEL_FILE = MODEL_MANAGER.getModelFile("org.example@1.0.0"); 32 | const CONCEPTS: ConceptDeclaration[] = MODEL_MANAGER.getConceptDeclarations(); 33 | const DECLARATIONS = MODEL_FILE.getAllDeclarations().map((decl) => decl.ast); 34 | 35 | /** 36 | * GET /connected-fields/type-names 37 | * Returns the verifiable concepts from model.cto 38 | */ 39 | export const getTypeNames = (_req: IReq, res: IRes) => { 40 | try { 41 | const typeNames: TypeNameInfo[] = [ 42 | { 43 | typeName: "BankAccountOpening", 44 | label: "Bank Account Opening" 45 | }, 46 | ]; 47 | const body = { typeNames }; 48 | return res.status(200).json(body).send(); 49 | } catch (err: any) { 50 | return res 51 | .status(500) 52 | .json(generateErrorResponse(ErrorCode.INTERNAL_ERROR, err?.message || err)) 53 | .send(); 54 | } 55 | }; 56 | 57 | export const getTypeDefinitions = (_req: IReq, res: IRes): IRes => { 58 | try { 59 | const defs: GetTypeDefinitionsResponse = { 60 | declarations: DECLARATIONS as unknown as import("@accordproject/concerto-types").DeclarationUnion[], 61 | }; 62 | 63 | return res.status(200).json(defs).send(); 64 | } catch (err: any) { 65 | return res 66 | .status(500) 67 | .json(generateErrorResponse(ErrorCode.INTERNAL_ERROR, err?.message || err)) 68 | .send(); 69 | } 70 | }; 71 | 72 | export const verify = (req: IReq, res: IRes): IRes => { 73 | const { typeName, data } = (req.body as unknown as VerifyBody); 74 | 75 | if (!typeName) { 76 | return res 77 | .status(400) 78 | .json(generateErrorResponse(ErrorCode.BAD_REQUEST, "Missing typeName in request")) 79 | .send(); 80 | } 81 | 82 | if (!data) { 83 | return res 84 | .status(400) 85 | .json(generateErrorResponse(ErrorCode.BAD_REQUEST, "Missing data in request")) 86 | .send(); 87 | } 88 | 89 | try { 90 | switch (typeName) { 91 | case "BankAccountOpening": { 92 | const result = verifyBankAccountOpening(data as any); 93 | const response: VerifyResponse = result.matched 94 | ? { 95 | verified: true, 96 | verifyResponseMessage: "Verification succeeded", 97 | } 98 | : { 99 | verified: false, 100 | verifyResponseMessage: "Verification failed", 101 | verifyFailureReason: result?.message ?? "Unknown reason", 102 | }; 103 | 104 | return res.status(200).json(response).send(); 105 | } 106 | 107 | default: 108 | return res 109 | .status(400) 110 | .json( 111 | generateErrorResponse( 112 | ErrorCode.BAD_REQUEST, 113 | `Type: [${typeName}] is not verifiable` 114 | ) 115 | ) 116 | .send(); 117 | } 118 | } catch (err: any) { 119 | console.error(`Verification error:`, err); 120 | return res 121 | .status(500) 122 | .json(generateErrorResponse(ErrorCode.INTERNAL_ERROR, err?.message || err)) 123 | .send(); 124 | } 125 | }; 126 | -------------------------------------------------------------------------------- /src/models/connectedfields.ts: -------------------------------------------------------------------------------- 1 | import { DeclarationUnion } from '@accordproject/concerto-types'; 2 | 3 | export interface CreateRecordResponse { 4 | /** 5 | * The identifier of the new record. 6 | * Note that the external source may not accept the provided identifier and choose its own. 7 | * In any case, this represents the actual record identifier applied, if record creation is successful. 8 | */ 9 | recordId: string; 10 | } 11 | 12 | export type GetTypeNamesBody = void; 13 | 14 | export type GetTypeNamesResponse = { 15 | /** 16 | * A collection of type names whose converted schemas the client is trying to retrieve. 17 | */ 18 | typeNames: TypeNameInfo[]; 19 | }; 20 | 21 | /** 22 | * The error information given when type fails to be retrieved or transformed 23 | */ 24 | export type GetTypeDefinitionsError = { 25 | typeName: string; 26 | code: GetTypeDefinitionsErrorCode; 27 | message: string; 28 | }; 29 | 30 | /** 31 | * An exhaustive set of reason codes for the failure 32 | */ 33 | export enum GetTypeDefinitionsErrorCode { 34 | SCHEMA_RETRIEVAL_FAILED, 35 | SCHEMA_TRANSFORMATION_FAILED, 36 | UNKNOWN, 37 | } 38 | 39 | export type TypeNameInfo = { 40 | /** 41 | * Name of the type 42 | */ 43 | typeName: string; 44 | 45 | /** 46 | * A display friendly name of the underlying type that can be used to render on UX canvases 47 | */ 48 | label: string; 49 | 50 | /** 51 | * A help text describing the purpose/use of the type 52 | */ 53 | description?: string; 54 | }; 55 | 56 | export type GetTypeDefinitionsBody = { 57 | /** 58 | * A collection of type names whose converted schemas the client is trying to retrieve. 59 | */ 60 | typeNames: string[]; 61 | }; 62 | 63 | export type GetTypeDefinitionsResponse = { 64 | /** 65 | * The converted list of schemas present in the external system 66 | * See https://concerto.accordproject.org/docs/design/specification/model-classes 67 | */ 68 | declarations: DeclarationUnion[]; 69 | 70 | /** 71 | * A list of errors associated with fetching or transforming the schemas 72 | */ 73 | errors?: GetTypeDefinitionsError[]; 74 | }; 75 | 76 | export type TypeField = { 77 | name: string; 78 | dataType: string; 79 | }; 80 | 81 | export type TypeDefinition = { 82 | typeName: string; 83 | fields: TypeField[]; 84 | }; 85 | 86 | export type GetTypeDefinitionsRecordResponse = { 87 | typeDefinitions: TypeDefinition[]; 88 | }; 89 | 90 | export type VerifyBody = { 91 | /** 92 | * The type name of the record that is being verified which can be retrieved using the GetTypeNames action. 93 | */ 94 | typeName: string; 95 | 96 | /** 97 | * A unique key the application may use to identify duplicate (retry) requests. 98 | */ 99 | idempotencyKey: string; 100 | 101 | /** 102 | * Data to verify 103 | */ 104 | data: object; 105 | }; 106 | 107 | export type VerifyResponse = { 108 | /** 109 | * Indicates whether the verification was successful or not. 110 | */ 111 | verified: boolean; 112 | 113 | /** 114 | * Provides information on the verification result. 115 | */ 116 | verifyResponseMessage: string; 117 | 118 | /** 119 | * (Optional) Provides the reason for verification failure, if the verification was unsuccessful. 120 | */ 121 | verifyFailureReason?: string; 122 | 123 | /** 124 | * (Optional) Code representing the specific result of the verification process. 125 | */ 126 | verificationResultCode?: string; 127 | 128 | /** 129 | * (Optional) A descriptive message providing more details about the verification result. 130 | */ 131 | verificationResultDescription?: string; 132 | 133 | /** 134 | * (Optional) A list of suggested actions or fixes that could resolve the verification failure. 135 | * Each object in the array contains information about a recommended fix. 136 | */ 137 | suggestions?: object[]; 138 | 139 | /** 140 | * (Optional) Any additional data or metadata that needs to be passed through from the verification process. This might contain information relevant for further processing or troubleshooting. 141 | */ 142 | passthroughResponseData?: object; 143 | }; 144 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Bank Account Opening", 3 | "description": { 4 | "short": "App for Bank Account Opening", 5 | "long": "This app is designed to allow users to open bank accounts using connected fields extensions" 6 | }, 7 | "termsOfServiceUrl": "https://www.johndoe.com/tos", 8 | "privacyUrl": "https://www.johndoe.com/privacy-security", 9 | "supportUrl": "https://www.johndoe.com/support", 10 | "publisher": { 11 | "name": "John Doe", 12 | "email": "john.doe@gmail.com", 13 | "phone": "800-867-5309", 14 | "website": "https://www.johndoe.com" 15 | }, 16 | "connections": [ 17 | { 18 | "name": "authentication", 19 | "description": "Secure connection to the connected fields proxy", 20 | "type": "oauth2", 21 | "params": { 22 | "provider": "CUSTOM", 23 | "clientId": "0fdcd8f777f49a6d79c4ffab28284903cb2a05d77f7fee26df813e5fb7712e28da8e4cf739f2e24539c9d090e10d879bf26c90884bd6086d38d3b2fa95961f7e", 24 | "clientSecret": "0fdcd8f777f49a6d79c4ffab28284903cb2a05d77f7fee26df813e5fb7712e28da8e4cf739f2e24539c9d090e10d879bf26c90884bd6086d38d3b2fa95961f7e", 25 | "scopes": [], 26 | "customConfig": { 27 | "authorizationMethod": "header", 28 | "authorizationParams": { 29 | "prompt": "consent", 30 | "access_type": "offline" 31 | }, 32 | "authorizationUrl": "https://51b9cd46977c.ngrok-free.app/api/oauth/authorize", 33 | "requiredScopes": [], 34 | "scopeSeparator": " ", 35 | "tokenUrl": "https://51b9cd46977c.ngrok-free.app/api/oauth/token", 36 | "refreshScopes": [] 37 | } 38 | } 39 | } 40 | ], 41 | "icon": { 42 | "data": "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABQVBMVEUAAAD/AACAAP//gID/VVX/Zmb/SUn/VVX/XV3/VVVLAP//S0v/UVFOAP//Tk7/VVX/UFD/VVX/U1P/UVGTIKb/U1NPAP//U1P/UFBLAP+HG7n/UVH/VFT/UVH/UVH/U1P/UVH/U1P/UVH/U1P/UlL/UVH/U1NNAP//UVH/UVH/UVFNAP//UlL/UlL/UlL/UlJLAP//UlL/UlL/U1MTAD5KGBheHx9HFhZGFhZFFhb/UlJMGRk+ExNNGBg8ExP/UlL/UlJAFBT/U1P/UlL/U1P/UlL/UlL/UlL/UlLZRkb/UlL/UlL/UlL/UlJDAOLiSUn/UlL/UlJEAOf/U1NGAO3/UlL/UVFHAPH/UlL/UlLxTU1MAP//UlIAAABMAP//UlL/UlJMAP8AAAD/UlL/UlIAAABMAP/9UVH+UlL/UlL///8T+Es2AAAAZXRSTlMAAQICAwUHCQsMEREWGhoeICQlJigoKiswM0JCRkhVVlhiZWlqd3h7h4qNj5OcoqWprK+2wMDAwcLDxMXIyMnKy8zMzc/T1tfd4uLk5ebo6Onq6+7v7/Hz8/T19vf5+fn6+/z8/hoS1SAAAAABYktHRGolYpUOAAABQElEQVRYw+3Wx1YCQRBG4TJjxBwxY8CAOWfBnBXMCqI1Wu//Am5cyDQ9Pe2/cTF339+qTlUTKU1kRNPD5VZ8sJEMVYuhRLTCE6gTY2fREgwQWW0AAbmJgIC894GAZLtBQNJNICDJMhCQIRS4rwEBiaFAOgQC0o8CcyjwXAkC0kXFrR35dR65e/QAhmnacXXO7nKLemCK3swA84J+MZDjB+A1HXDsE+Al3Sj5BXhZsxV8A7zyBQK8Xki4tQB4p4BwagPw5qcCbFsBvKEAs3ZATpnqUTuAL9xADwqEQeCAQGAMBdpBYJdAoBcE9kpBIEIYMEkYsB/CgKuff9ZfgZM2goBEPSFANlZOWiBlBDLxll+3VAGc+RcP4ONwZiD/Y+N4dJdydd1cpFxzx6paCoAACIB/CzxZAVUqMGIhvI6r778B8fsX3rztq9YAAAAASUVORK5CYII=", 43 | "mediaType": "image/png" 44 | }, 45 | "screenshots": [], 46 | "extensions": [ 47 | { 48 | "name": "My Connected Fields Extension", 49 | "description": "Used to verify and autofill agreements with custom data models", 50 | "template": "ConnectedFields.Version1.ConnectedFields", 51 | "actionReferences": [ 52 | "My Verify Action", 53 | "My GetTypeNames Action", 54 | "My GetTypeDefinitions Action" 55 | ] 56 | } 57 | ], 58 | "actions": [ 59 | { 60 | "name": "My Verify Action", 61 | "description": "This is a description of my verify action", 62 | "template": "ConnectedFields.Version1.Verify", 63 | "connectionsReference": "authentication", 64 | "params": { 65 | "uri": "https://51b9cd46977c.ngrok-free.app/api/connectedfields/verify" 66 | } 67 | }, 68 | { 69 | "name": "My GetTypeNames Action", 70 | "description": "This is a description of my GetTypeNames action", 71 | "template": "DataIO.Version6.GetTypeNames", 72 | "connectionsReference": "authentication", 73 | "params": { 74 | "uri": "https://51b9cd46977c.ngrok-free.app/api/connectedfields/getTypeNames" 75 | } 76 | }, 77 | { 78 | "name": "My GetTypeDefinitions Action", 79 | "description": "This is a description of my GetTypeDefinitions action", 80 | "template": "DataIO.Version6.GetTypeDefinitions", 81 | "connectionsReference": "authentication", 82 | "params": { 83 | "uri": "https://51b9cd46977c.ngrok-free.app/api/connectedfields/getTypeDefinitions" 84 | } 85 | } 86 | ], 87 | "publicationRegions": [ 88 | "US" 89 | ], 90 | "distribution": "PUBLIC" 91 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 8 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | // "lib": [], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | "outDir": "dist", /* Redirect output structure to the directory. */ 18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | "strict": true, /* Enable all strict type-checking options. */ 29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | 43 | /* Module Resolution Options */ 44 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 45 | "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 46 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 47 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 48 | // "typeRoots": [], /* List of folders to include type definitions from. */ 49 | // "types": [], /* Type declaration files to be included in compilation. */ 50 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 51 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 52 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 53 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 54 | 55 | /* Source Map Options */ 56 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 59 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 60 | 61 | /* Experimental Options */ 62 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 63 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 64 | 65 | /* Advanced Options */ 66 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 67 | "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ 68 | "useUnknownInCatchVariables": false, 69 | "sourceMap": false, 70 | "removeComments": true, 71 | "resolveJsonModule": true, 72 | }, 73 | "include": [ 74 | "src/**/*.ts", 75 | "./src/**/*.cto", 76 | "build.ts" 77 | ], 78 | "exclude": [ 79 | "src/public/", 80 | ] 81 | } -------------------------------------------------------------------------------- /post-workshop-resources/postWorkshopserver.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Rename this to server.js after you've completed the workshop to see the full version. 4 | 5 | const express = require('express'); 6 | const axios = require('axios'); 7 | const session = require('express-session'); 8 | const dotenv = require('dotenv'); 9 | const crypto = require('crypto'); 10 | const iam = require('@docusign/iam-sdk'); 11 | 12 | dotenv.config({ path: './settings.txt' }); 13 | 14 | const app = express(); 15 | const port = process.env.PORT || 4000; 16 | 17 | // Debugging helper - uncomment to verify settings load 18 | // console.log('Loaded settings from settings.txt'); 19 | // console.log('Account ID:', process.env.DS_ACCOUNT_ID); 20 | 21 | app.use(session({ 22 | secret: process.env.SESSION_SECRET || 'dev-secret', 23 | resave: false, 24 | saveUninitialized: true, 25 | cookie: { sameSite: 'lax' } 26 | })); 27 | 28 | // Helper function to verify required env vars 29 | function ensureEnv(...keys) { 30 | const missing = keys.filter(k => !process.env[k]); 31 | if (missing.length) { 32 | console.error('Missing settings keys:', missing.join(', ')); 33 | process.exit(1); 34 | } 35 | } 36 | 37 | ensureEnv( 38 | 'DS_AUTH_SERVER', 39 | 'DS_CLIENT_ID', 40 | 'DS_CLIENT_SECRET', 41 | 'DS_REDIRECT_URI', 42 | 'DS_API_BASE_PATH', 43 | 'DS_ACCOUNT_ID', 44 | 'MAESTRO_WORKFLOW_ID' 45 | ); 46 | 47 | // Home page 48 | app.get('/', (req, res) => { 49 | const loggedIn = !!req.session.accessToken; 50 | res.type('html').send(` 51 | 52 | Discover Workshop - Workflow Triggering 53 | 54 |

Trigger a Maestro workflow instance

55 |

Account ID: ${process.env.DS_ACCOUNT_ID}

56 | ${loggedIn 57 | ? ` 58 |

Log out

` 59 | : ``} 60 | 61 | 62 | `); 63 | }); 64 | 65 | // Login function: redirect to OAuth authorization endpoint 66 | app.get('/login', (req, res) => { 67 | const state = crypto.randomBytes(16).toString('hex'); 68 | req.session.oauthState = state; 69 | 70 | const authUrl = 71 | `${process.env.DS_AUTH_SERVER}/oauth/auth` + 72 | `?response_type=code` + 73 | `&scope=${encodeURIComponent('signature aow_manage')}` + 74 | `&client_id=${encodeURIComponent(process.env.DS_CLIENT_ID)}` + 75 | `&redirect_uri=${encodeURIComponent(process.env.DS_REDIRECT_URI)}` + 76 | `&state=${encodeURIComponent(state)}`; 77 | 78 | res.redirect(authUrl); 79 | }); 80 | 81 | // OAuth callback: exchange code for access_token 82 | app.get('/callback', async (req, res) => { 83 | const { code, state } = req.query || {}; 84 | if (!code) return res.status(400).send('Missing ?code='); 85 | 86 | if (!state || state !== req.session.oauthState) { 87 | return res.status(400).send('Invalid state'); 88 | } 89 | delete req.session.oauthState; 90 | 91 | try { 92 | const basic = Buffer.from( 93 | `${process.env.DS_CLIENT_ID}:${process.env.DS_CLIENT_SECRET}` 94 | ).toString('base64'); 95 | 96 | const tokenRes = await axios.post( 97 | `${process.env.DS_AUTH_SERVER}/oauth/token`, 98 | new URLSearchParams({ 99 | grant_type: 'authorization_code', 100 | code, 101 | redirect_uri: process.env.DS_REDIRECT_URI 102 | }), 103 | { 104 | headers: { 105 | 'Authorization': `Basic ${basic}`, 106 | 'Content-Type': 'application/x-www-form-urlencoded' 107 | } 108 | } 109 | ); 110 | 111 | const accessToken = tokenRes.data?.access_token; 112 | if (!accessToken || typeof accessToken !== 'string') { 113 | console.error('Token response:', tokenRes.data); 114 | return res.status(500).send('Did not receive a valid access_token'); 115 | } 116 | 117 | req.session.accessToken = accessToken; 118 | req.session.tokenReceivedAt = Date.now(); 119 | req.session.expiresIn = tokenRes.data?.expires_in; 120 | 121 | // Debugging helper - uncomment to verify token 122 | //console.log('Logged in. Token:', accessToken); 123 | res.redirect('/'); 124 | } catch (err) { 125 | console.error('OAuth exchange failed:', err.response?.data || err.message); 126 | res.status(500).send('Login failed (see server logs).'); 127 | } 128 | }); 129 | 130 | // Trigger workflow function 131 | app.get("/trigger", async (req, res) => { 132 | const token = req.session.accessToken; 133 | if (!token) return res.redirect("/login"); 134 | 135 | try { 136 | const accountId = process.env.DS_ACCOUNT_ID; 137 | const workflowId = process.env.MAESTRO_WORKFLOW_ID; 138 | 139 | const client = new iam.IamClient({ accessToken: token }); 140 | 141 | // Retrieve trigger requirements 142 | // Comment this out if you don't want to fetch requirements first 143 | const requirements = await client.maestro.workflows.getWorkflowTriggerRequirements({ 144 | accountId, 145 | workflowId, 146 | }); 147 | 148 | console.log("Trigger Requirements:"); 149 | console.log(JSON.stringify(requirements, null, 2)); 150 | // End retrieve trigger requirements 151 | 152 | const triggerInputs = { 153 | startDate: "2024-10-30", 154 | }; 155 | 156 | const triggerWorkflowPayload = { 157 | instanceName: "Raileen's Super Cool Workflow", 158 | triggerInputs, 159 | }; 160 | 161 | // Debugging helper - uncomment to verify values 162 | // console.log("Workflow ID:", workflowId); 163 | // console.log("Trigger inputs:", JSON.stringify(triggerWorkflowPayload, null, 2)); 164 | 165 | // Call the Maestro triggerWorkflow API via the SDK 166 | const result = await client.maestro.workflows.triggerWorkflow({ 167 | accountId, 168 | workflowId, 169 | triggerWorkflow: triggerWorkflowPayload, 170 | }); 171 | 172 | // Debugging helper -uncomment to verify response 173 | // console.log("Response: "); 174 | // console.log(JSON.stringify(result, null, 2)); 175 | 176 | const instanceUrl = result?.instanceUrl; 177 | 178 | res 179 | .status(200) 180 | .type("html") 181 | .send(` 182 |

Workflow Instance Triggered! Yay!

${JSON.stringify(result, null, 2)}
183 |

Instance URL: ${instanceUrl}

184 | 190 |
191 |

Full Response

192 |
${JSON.stringify(result, null, 2)}
193 | `); 194 | 195 | } catch (err) { 196 | console.error("Failed to trigger workflow:"); 197 | console.error("Error:", err.message); 198 | console.error("Response:", err.response?.data || err); 199 | 200 | res.status(500).send(` 201 |

Failed to start workflow

202 |
${JSON.stringify(err.response?.data || err.message, null, 2)}
203 | `); 204 | } 205 | }); 206 | 207 | // Logout (clear session) 208 | app.get('/logout', (req, res) => { 209 | req.session.destroy(() => res.redirect('/')); 210 | }); 211 | 212 | // Start server 213 | app.listen(port, () => { 214 | console.error("Running on: "); 215 | console.log(`http://localhost:${port}`); 216 | }); 217 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const express = require('express'); 4 | const axios = require('axios'); 5 | const session = require('express-session'); 6 | const dotenv = require('dotenv'); 7 | const crypto = require('crypto'); 8 | const iam = require('@docusign/iam-sdk'); 9 | 10 | dotenv.config({ path: './settings.txt' }); 11 | 12 | const app = express(); 13 | const port = process.env.PORT || 4000; 14 | 15 | // Debugging helper - uncomment to verify settings load 16 | // console.log('Loaded settings from settings.txt'); 17 | // console.log('Account ID:', process.env.DS_ACCOUNT_ID); 18 | 19 | app.use(session({ 20 | secret: process.env.SESSION_SECRET || 'dev-secret', 21 | resave: false, 22 | saveUninitialized: true, 23 | cookie: { sameSite: 'lax' } 24 | })); 25 | 26 | // Helper function to verify required env vars 27 | function ensureEnv(...keys) { 28 | const missing = keys.filter(k => !process.env[k]); 29 | if (missing.length) { 30 | console.error('Missing settings keys:', missing.join(', ')); 31 | process.exit(1); 32 | } 33 | } 34 | 35 | ensureEnv( 36 | 'DS_AUTH_SERVER', 37 | 'DS_CLIENT_ID', 38 | 'DS_CLIENT_SECRET', 39 | 'DS_REDIRECT_URI', 40 | 'DS_API_BASE_PATH', 41 | 'DS_ACCOUNT_ID', 42 | 'MAESTRO_WORKFLOW_ID' 43 | ); 44 | 45 | // Home page 46 | app.get('/', (req, res) => { 47 | const loggedIn = !!req.session.accessToken; 48 | res.type('html').send(` 49 | 50 | Discover Workshop - Workflow Triggering 51 | 52 |

Trigger a Maestro workflow instance

53 |

Account ID: ${process.env.DS_ACCOUNT_ID}

54 | ${loggedIn 55 | ? ` 56 |

Log out

` 57 | : ``} 58 | 59 | 60 | `); 61 | }); 62 | 63 | // Login function: redirect to OAuth authorization endpoint 64 | app.get('/login', (req, res) => { 65 | const state = crypto.randomBytes(16).toString('hex'); 66 | req.session.oauthState = state; 67 | 68 | const authUrl = 69 | `${process.env.DS_AUTH_SERVER}/oauth/auth` + 70 | `?response_type=code` + 71 | `&scope=${encodeURIComponent('signature aow_manage')}` + 72 | `&client_id=${encodeURIComponent(process.env.DS_CLIENT_ID)}` + 73 | `&redirect_uri=${encodeURIComponent(process.env.DS_REDIRECT_URI)}` + 74 | `&state=${encodeURIComponent(state)}`; 75 | 76 | res.redirect(authUrl); 77 | }); 78 | 79 | // OAuth callback: exchange code for access_token 80 | app.get('/callback', async (req, res) => { 81 | const { code, state } = req.query || {}; 82 | if (!code) return res.status(400).send('Missing ?code='); 83 | 84 | if (!state || state !== req.session.oauthState) { 85 | return res.status(400).send('Invalid state'); 86 | } 87 | delete req.session.oauthState; 88 | 89 | try { 90 | const basic = Buffer.from( 91 | `${process.env.DS_CLIENT_ID}:${process.env.DS_CLIENT_SECRET}` 92 | ).toString('base64'); 93 | 94 | const tokenRes = await axios.post( 95 | `${process.env.DS_AUTH_SERVER}/oauth/token`, 96 | new URLSearchParams({ 97 | grant_type: 'authorization_code', 98 | code, 99 | redirect_uri: process.env.DS_REDIRECT_URI 100 | }), 101 | { 102 | headers: { 103 | 'Authorization': `Basic ${basic}`, 104 | 'Content-Type': 'application/x-www-form-urlencoded' 105 | } 106 | } 107 | ); 108 | 109 | const accessToken = tokenRes.data?.access_token; 110 | if (!accessToken || typeof accessToken !== 'string') { 111 | console.error('Token response:', tokenRes.data); 112 | return res.status(500).send('Did not receive a valid access_token'); 113 | } 114 | 115 | req.session.accessToken = accessToken; 116 | req.session.tokenReceivedAt = Date.now(); 117 | req.session.expiresIn = tokenRes.data?.expires_in; 118 | 119 | // Debugging helper - uncomment to verify token 120 | //console.log('Logged in. Token:', accessToken); 121 | res.redirect('/'); 122 | } catch (err) { 123 | console.error('OAuth exchange failed:', err.response?.data || err.message); 124 | res.status(500).send('Login failed (see server logs).'); 125 | } 126 | }); 127 | 128 | // Trigger workflow function 129 | app.get("/trigger", async (req, res) => { 130 | const token = req.session.accessToken; 131 | if (!token) return res.redirect("/login"); 132 | 133 | try { 134 | const accountId = process.env.DS_ACCOUNT_ID; 135 | const workflowId = process.env.MAESTRO_WORKFLOW_ID; 136 | 137 | const client = new iam.IamClient({ accessToken: token }); 138 | 139 | // ========================== TASK 1 ========================= 140 | // Make an API call to retrieve workflow trigger requirements 141 | // The endpoint is: GET /v2.1/accounts/{accountId}/maestro/workflows/{workflowId}/triggerRequirements 142 | // SDK method: client.maestro.workflows.getWorkflowTriggerRequirements 143 | // See code example here: https://developers.docusign.com/docs/maestro-api/how-to/trigger-workflow/ 144 | // Corresponds to step 3 + 4 145 | // API Ref: https://developers.docusign.com/docs/maestro-api/reference/maestro/workflows/getworkflowtriggerrequirements/ 146 | 147 | console.log("Trigger Requirements:"); 148 | console.log(JSON.stringify(requirements, null, 2)); 149 | // End retrieve trigger requirements 150 | 151 | 152 | const triggerInputs = { 153 | // Trigger requirements key-value pairs go here 154 | // e.g., "inputName": "inputValue" 155 | }; 156 | 157 | // Name your instance 158 | const triggerWorkflowPayload = { 159 | instanceName: "", 160 | triggerInputs, 161 | }; 162 | 163 | // ========================== TASK 1 end ========================= 164 | 165 | // Debugging helper - uncomment to verify values 166 | // console.log("Workflow ID:", workflowId); 167 | // console.log("Trigger inputs:", JSON.stringify(triggerWorkflowPayload, null, 2)); 168 | 169 | // ========================== TASK 2 ========================== 170 | // Call the Maestro triggerWorkflow API via the SDK 171 | // SDK method: client.maestro.workflows.triggerWorkflow 172 | // Step 5 of code example linked above 173 | // API Ref: https://developers.docusign.com/docs/maestro-api/reference/maestro/workflows/triggerworkflow/ 174 | // Hint: pay close attention to the required fields for the request body 175 | 176 | 177 | //========================== TASK 2 end ========================= 178 | 179 | 180 | // Debugging helper -uncomment to verify response 181 | // console.log("Response: "); 182 | // console.log(JSON.stringify(result, null, 2)); 183 | 184 | const instanceUrl = result?.instanceUrl; 185 | 186 | res 187 | .status(200) 188 | .type("html") 189 | 190 | // ========================== TASK 3 ========================== 191 | // Display the instanceUrl as a clickable link and embedded iframe 192 | // Step 6 of the corresponding code example linked above 193 | .send(` 194 |

Workflow Instance Triggered! Yay!

${JSON.stringify(result, null, 2)}
195 | 196 | 197 | 198 | 199 |
200 |

Full Response

201 |
${JSON.stringify(result, null, 2)}
202 | `); 203 | 204 | // ========================== TASK 3 end ========================== 205 | 206 | } catch (err) { 207 | console.error("Failed to trigger workflow:"); 208 | console.error("Error:", err.message); 209 | console.error("Response:", err.response?.data || err); 210 | 211 | res.status(500).send(` 212 |

Failed to start workflow

213 |
${JSON.stringify(err.response?.data || err.message, null, 2)}
214 | `); 215 | } 216 | }); 217 | 218 | // Logout (clear session) 219 | app.get('/logout', (req, res) => { 220 | req.session.destroy(() => res.redirect('/')); 221 | }); 222 | 223 | // Start server 224 | app.listen(port, () => { 225 | console.error("Running on: "); 226 | console.log(`http://localhost:${port}`); 227 | }); 228 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Discover Workshop — Bank Account Opening 2 | 3 | Building the Connected Fields extension app. 4 | 5 | --- 6 | 7 | ## Prerequisites 8 | 9 | Before the workshop, ensure you have: 10 | 11 | - Docusign developer account (signup link: https://developers.docusign.com/) 12 | - Node.js and npm 13 | - ngrok (or Cloudflared as backup) 14 | - Optional: Docker Desktop (useful if ngrok is blocked) 15 | 16 | ## 1. Clone the repository 17 | 18 | ```bash 19 | git clone https://github.com/docusign/docusign-discover-workshop-1.git 20 | ``` 21 | 22 | --- 23 | 24 | ## 2. Add sample data 25 | 26 | Add entries to `src/db/bankAccount.json`. Example entry: 27 | 28 | ```json 29 | { 30 | "id": "5", 31 | "routingNumber": "443980657", 32 | "accountNumber": "1122334444", 33 | "accountType": "checking", 34 | "accountHolderName": "Discover Workshop", 35 | "bankName": "CitiBank", 36 | "status": "active" 37 | } 38 | ``` 39 | 40 | Add as many entries as you like. 41 | 42 | --- 43 | 44 | ## 3. Generate secret values 45 | 46 | Run this command **four** times and save each value: 47 | 48 | ```bash 49 | node -e "console.log(require('crypto').randomBytes(64).toString('hex'));" 50 | ``` 51 | 52 | You will use these values in the next step. 53 | 54 | --- 55 | 56 | ## 4. Set environment variables 57 | 58 | - Copy `example.development.env` to `development.env`. 59 | - Replace the following values with your generated secrets: 60 | - `JWT_SECRET_KEY` 61 | - `OAUTH_CLIENT_ID` 62 | - `OAUTH_CLIENT_SECRET` 63 | - `AUTHORIZATION_CODE` 64 | 65 | --- 66 | 67 | ## 5. Install dependencies 68 | 69 | ```bash 70 | npm install 71 | ``` 72 | 73 | --- 74 | 75 | ## 6. Run the proxy server 76 | 77 | ```bash 78 | npm run dev 79 | ``` 80 | 81 | This starts a local server on the port defined in `development.env` (default: `3000`). 82 | 83 | --- 84 | 85 | ## 7. Start ngrok (or Cloudflared) 86 | 87 | Start ngrok to expose localhost: 88 | 89 | ```bash 90 | ngrok http 3000 91 | ``` 92 | 93 | If ngrok is blocked or assigns problematic `.dev` domains, you can run it via Docker: 94 | 95 | ```bash 96 | docker run -it -e NGROK_AUTHTOKEN= ngrok/ngrok http host.docker.internal:3000 97 | ``` 98 | 99 | Optional: Use Cloudflared (macOS/Homebrew example) 100 | 101 | Install Homebrew (if needed): 102 | 103 | ```bash 104 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 105 | ``` 106 | 107 | Install cloudflared: 108 | 109 | ```bash 110 | brew install cloudflared 111 | ``` 112 | 113 | Start a Cloudflare Tunnel: 114 | 115 | ```bash 116 | cloudflared tunnel --url http://localhost:3000 117 | ``` 118 | 119 | You can also download cloudflared from the official installation guide. 120 | 121 | --- 122 | 123 | ## 8. Save the forwarding address 124 | 125 | Copy the forwarding address from ngrok/cloudflared output — you will use this in the manifest. 126 | 127 | Example ngrok output excerpt (for reference): 128 | 129 | ``` 130 | Session Status online 131 | Forwarding https://bbd7-12-202-171-35.ngrok-free.app -> http://localhost:3000 132 | Web Interface http://127.0.0.1:4040 133 | ``` 134 | 135 | --- 136 | 137 | ## 9. Prepare your app manifest 138 | 139 | In `manifest.json`: 140 | 141 | - Replace `` with your ngrok/cloudflared forwarding address in: 142 | - `connections.params.customConfig.tokenUrl` 143 | - `connections.params.customConfig.authorizationUrl` 144 | - `actions.params.uri` (for all actions) 145 | 146 | - Replace these client values with generated values from step 3: 147 | - `clientId` → `OAUTH_CLIENT_ID` (development.env) 148 | - `clientSecret` → `OAUTH_CLIENT_SECRET` (development.env) 149 | 150 | (lines referenced in the source manifest: clientId ~ line 23, clientSecret ~ line 24) 151 | 152 | --- 153 | 154 | ## 10. Upload your manifest and create the Bank Account Registration app 155 | 156 | - Go to Docusign Developer Console: https://devconsole.docusign.com/apps 157 | - Create App → By editing the manifest. 158 | - Paste or upload `manifest.json` and select Validate → Create App. 159 | 160 | --- 161 | 162 | ## 11. Console tests 163 | 164 | - Open the new app → App Testing → Install app. 165 | - Run the connection test (click Run Test → Visit site → consent). 166 | - Run `getTypeNames` (default request body). 167 | - Run `getTypeDefinitions` (default request body) — returns large declarations object. 168 | 169 | Verify extension tests — example request bodies and expected responses below. 170 | 171 | Testing success (should verify): 172 | 173 | ```json 174 | { 175 | "typeName": "BankAccountOpening", 176 | "idempotencyKey": "mock-bank-open-001", 177 | "data": { 178 | "routingNumber": "111000025", 179 | "accountNumber": "1234567890", 180 | "accountHolderName": "John Doe", 181 | "bankName": "Bank of America" 182 | } 183 | } 184 | ``` 185 | 186 | Response: 187 | 188 | ```json 189 | { 190 | "verified": true, 191 | "verifyResponseMessage": "Verification succeeded" 192 | } 193 | ``` 194 | 195 | Testing blocked account (should fail with blocked reason): 196 | 197 | ```json 198 | { 199 | "typeName": "BankAccountOpening", 200 | "idempotencyKey": "mock-bank-open-001", 201 | "data": { 202 | "routingNumber": "222000111", 203 | "accountNumber": "9876543210", 204 | "accountHolderName": "Jane Smith", 205 | "bankName": "Chase Bank" 206 | } 207 | } 208 | ``` 209 | 210 | Response: 211 | 212 | ```json 213 | { 214 | "verified": false, 215 | "verifyResponseMessage": "Verification failed", 216 | "verifyFailureReason": "This account is blocked" 217 | } 218 | ``` 219 | 220 | Testing not-found (guaranteed failure): 221 | 222 | ```json 223 | { 224 | "typeName": "BankAccountOpening", 225 | "idempotencyKey": "mock-bank-open-001", 226 | "data": { 227 | "routingNumber": "111000022", 228 | "accountNumber": "1234567890", 229 | "accountHolderName": "John Doe", 230 | "bankName": "Bank of America" 231 | } 232 | } 233 | ``` 234 | 235 | Response: 236 | 237 | ```json 238 | { 239 | "verified": false, 240 | "verifyResponseMessage": "Verification failed", 241 | "verifyFailureReason": "No matching bank account record found" 242 | } 243 | ``` 244 | 245 | --- 246 | 247 | # Building the Maestro workflow 248 | 249 | ## Web Form Template (create in Docusign web forms) 250 | 251 | 1. Go to: https://apps-d.docusign.com/send/forms 252 | Click Start → Web Forms → Create Web Form 253 | 2. Choose “Start from scratch” → Next 254 | 3. Name the web form (e.g., “Bank Account Details”) → Apply 255 | 4. Configure pages and add fields. Add these Text Fields (required): 256 | - Email (API reference name: `email`) 257 | - Account Holder Name (API reference name: `accountHolderName`) 258 | - Bank Name (API reference name: `bankName`) 259 | - Account Number (API reference name: `accountNumber`) 260 | - Routing Number (API reference name: `routingNumber`) 261 | 5. Save → Activate. Set Access setting to “Public” → Activate. 262 | 263 | --- 264 | 265 | ## Envelope Template 266 | 267 | 1. Go to: https://apps-d.docusign.com/send/templates 268 | Start → Envelope Templates → Create a Template 269 | 2. Fill Template Name (e.g., “New Account Registration”), add `Account Registration Form - DocuCo.pdf` from repository. 270 | 3. Add a recipient role (e.g., “Account Holder” — leave name/email blank). 271 | 4. Envelope Types → Select “Bank Account Opening Agreements”. 272 | 5. In the Document Editor: 273 | - Switch to “Custom Fields” → App Fields → expand your uploaded app (e.g., “Bank Account Opening”). 274 | - Drag and place the app fields (Account Holder Name, Account Number, Bank Name, Routing Number) onto the PDF. 275 | - For each field, enable “Must verify to sign” under Data Verification. 276 | - Optionally rename Data Label to readable names (e.g., `accountNumber`). 277 | - Add Signature and Date Signed standard fields. 278 | 6. Save and Close → confirm template appears in “My Templates”. 279 | 280 | --- 281 | 282 | ## Maestro Workflow Creation 283 | 284 | 1. Go to: https://apps-d.docusign.com/send/workflows → Create Workflow → New Canvas → Continue 285 | 2. Add workflow start → “From an API call” → Next 286 | 3. Add Text variables: 287 | - `email` 288 | - `accountHolderName` 289 | - `bankName` 290 | - `accountNumber` 291 | - `routingNumber` 292 | Click Next → choose “Human” for starter → Apply 293 | 4. Add step: Collect Data with Web Forms 294 | - Configure: select the web form (“Bank Account Details”) 295 | - Add Participant → role: “Account Holder” 296 | - Map workflow variables to form fields → Apply 297 | 5. Add step: Prepare eSignature Template 298 | - Configure: select the envelope template (“New Account Registration”) 299 | - Map template fields to the Web Form values → Apply 300 | 6. Add step: Send Documents for Signature 301 | - Choose prepared template → Use a direct signing session 302 | - Map recipient name/email to Web Form values (Account Holder name/email) 303 | - Apply 304 | 7. Add step: Show a Confirmation Screen 305 | - Participant: Account Holder 306 | - Message title: “Account Registration Submitted” 307 | - Message body: “Thank you for submitting the Account Registration form. Please inform us if you want to withdraw this in the future.” 308 | - Apply 309 | 8. Add path end node → Review & Publish 310 | - Set workflow name: “Account Registration Flow” 311 | - Fix any validation errors, then Publish 312 | - Authorize application senders if prompted 313 | 314 | --- 315 | 316 | ## Testing the Maestro Workflow 317 | 318 | 1. Go to: https://apps-d.docusign.com/send/workflows 319 | 2. Locate your published workflow → Run Workflow 320 | 3. On “Start this flow manually” enter required fields and click Start 321 | 4. A new tab opens the web form. Fill with test data (blocked example): 322 | 323 | - Email: 324 | - Account Holder Name: Jane Smith 325 | - Bank Name: Chase Bank 326 | - Account Number: 9876543210 327 | - Routing Number: 222000111 328 | 329 | 5. Submit the form → complete signing; you should see validation errors if using blocked data. Replace with valid data (example success): 330 | 331 | - Account Holder Name: John Doe 332 | - Bank Name: Bank of America 333 | - Account Number: 1234567890 334 | - Routing Number: 111000025 335 | 336 | 6. Complete signing → confirm workflow success on the confirmation screen. 337 | 338 | --- 339 | 340 | # Trigger a workflow instance using the Maestro API 341 | 342 | ## Create integration key and configure settings 343 | 344 | 1. Go to Docusign Developer Center: https://developers.docusign.com/ → Log in 345 | 2. Profile → My Apps and Keys → Add App and Integration Key 346 | 3. Save: 347 | - Integration Key 348 | - Add Secret Key (save) 349 | 4. Under Additional settings → Redirect URIs add: 350 | - http://localhost:4000 351 | - http://localhost:4000/callback 352 | Save. 353 | 354 | 5. Copy from Apps and Keys page: 355 | - User ID 356 | - API Account ID 357 | 6. In Maestro Workflows (Agreements → Maestro Workflows) find your published workflow and copy the workflow ID from the URL. 358 | 359 | 7. Rename `example.settings.txt` to `settings.txt` and update values: 360 | 361 | ``` 362 | DS_CLIENT_ID=YOUR_INTEGRATION_KEY 363 | DS_CLIENT_SECRET=YOUR_SECRET 364 | DS_ACCOUNT_ID=PASTE_YOUR_API_ACCOUNT_ID 365 | MAESTRO_WORKFLOW_ID=YOUR_WORKFLOW_ID 366 | ``` 367 | 368 | --- 369 | 370 | ## Complete the code tasks 371 | 372 | Open `server.js` and find the `/trigger` route. Three tasks: 373 | 374 | - TASK 1 — Get trigger requirements & set inputs 375 | - TASK 2 — Trigger the workflow 376 | - TASK 3 — Show the instance URL and embed it in an iframe 377 | 378 | Helpful resources: 379 | - Maestro code example (sample code for finding trigger requirements, triggering the workflow, and embedding): https://developers.docusign.com/docs/maestro-api/how-to/trigger-workflow/ 380 | - API: getWorkflowTriggerRequirements: https://developers.docusign.com/docs/maestro-api/reference/maestro/workflows/getworkflowtriggerrequirements/ 381 | - API: triggerWorkflow: https://developers.docusign.com/docs/maestro-api/reference/maestro/workflows/triggerworkflow/ 382 | 383 | Hint: Pay attention to the required fields for the request body. 384 | 385 | --- 386 | 387 | ## Trigger the workflow locally 388 | 389 | Start the trigger server: 390 | 391 | ```bash 392 | npm run trigger 393 | ``` 394 | 395 | Open: http://localhost:4000 396 | Click “Log into your Docusign developer account” → grant consent → you’ll be redirected back and see your Account ID and a Trigger button. Click “Trigger Workflow Instance” to display the instance URL and embedded iframe. 397 | 398 | --- 399 | 400 | Feel free to repeat tests, modify the forms/templates/workflow, and experiment with more sample data. 401 | -------------------------------------------------------------------------------- /src/constants/http.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len */ 2 | /** 3 | * This file was copied from here: https://gist.github.com/scokmen/f813c904ef79022e84ab2409574d1b45 4 | */ 5 | 6 | /** 7 | * Hypertext Transfer Protocol (HTTP) response status codes. 8 | * @see {@link https://en.wikipedia.org/wiki/List_of_HTTP_status_codes} 9 | */ 10 | enum HttpStatusCodes { 11 | /** 12 | * The server has received the request headers and the client should proceed to send the request body 13 | * (in the case of a request for which a body needs to be sent; for example, a POST request). 14 | * Sending a large request body to a server after a request has been rejected for inappropriate headers would be inefficient. 15 | * To have a server check the request's headers, a client must send Expect: 100-continue as a header in its initial request 16 | * and receive a 100 Continue status code in response before sending the body. The response 417 Expectation Failed indicates the request should not be continued. 17 | */ 18 | CONTINUE = 100, 19 | 20 | /** 21 | * The requester has asked the server to switch protocols and the server has agreed to do so. 22 | */ 23 | SWITCHING_PROTOCOLS = 101, 24 | 25 | /** 26 | * A WebDAV request may contain many sub-requests involving file operations, requiring a long time to complete the request. 27 | * This code indicates that the server has received and is processing the request, but no response is available yet. 28 | * This prevents the client from timing out and assuming the request was lost. 29 | */ 30 | PROCESSING = 102, 31 | 32 | /** 33 | * Standard response for successful HTTP requests. 34 | * The actual response will depend on the request method used. 35 | * In a GET request, the response will contain an entity corresponding to the requested resource. 36 | * In a POST request, the response will contain an entity describing or containing the result of the action. 37 | */ 38 | OK = 200, 39 | 40 | /** 41 | * The request has been fulfilled, resulting in the creation of a new resource. 42 | */ 43 | CREATED = 201, 44 | 45 | /** 46 | * The request has been accepted for processing, but the processing has not been completed. 47 | * The request might or might not be eventually acted upon, and may be disallowed when processing occurs. 48 | */ 49 | ACCEPTED = 202, 50 | 51 | /** 52 | * SINCE HTTP/1.1 53 | * The server is a transforming proxy that received a 200 OK from its origin, 54 | * but is returning a modified version of the origin's response. 55 | */ 56 | NON_AUTHORITATIVE_INFORMATION = 203, 57 | 58 | /** 59 | * The server successfully processed the request and is not returning any content. 60 | */ 61 | NO_CONTENT = 204, 62 | 63 | /** 64 | * The server successfully processed the request, but is not returning any content. 65 | * Unlike a 204 response, this response requires that the requester reset the document view. 66 | */ 67 | RESET_CONTENT = 205, 68 | 69 | /** 70 | * The server is delivering only part of the resource (byte serving) due to a range header sent by the client. 71 | * The range header is used by HTTP clients to enable resuming of interrupted downloads, 72 | * or split a download into multiple simultaneous streams. 73 | */ 74 | PARTIAL_CONTENT = 206, 75 | 76 | /** 77 | * The message body that follows is an XML message and can contain a number of separate response codes, 78 | * depending on how many sub-requests were made. 79 | */ 80 | MULTI_STATUS = 207, 81 | 82 | /** 83 | * The members of a DAV binding have already been enumerated in a preceding part of the (multistatus) response, 84 | * and are not being included again. 85 | */ 86 | ALREADY_REPORTED = 208, 87 | 88 | /** 89 | * The server has fulfilled a request for the resource, 90 | * and the response is a representation of the result of one or more instance-manipulations applied to the current instance. 91 | */ 92 | IM_USED = 226, 93 | 94 | /** 95 | * Indicates multiple options for the resource from which the client may choose (via agent-driven content negotiation). 96 | * For example, this code could be used to present multiple video format options, 97 | * to list files with different filename extensions, or to suggest word-sense disambiguation. 98 | */ 99 | MULTIPLE_CHOICES = 300, 100 | 101 | /** 102 | * This and all future requests should be directed to the given URI. 103 | */ 104 | MOVED_PERMANENTLY = 301, 105 | 106 | /** 107 | * This is an example of industry practice contradicting the standard. 108 | * The HTTP/1.0 specification (RFC 1945) required the client to perform a temporary redirect 109 | * (the original describing phrase was "Moved Temporarily"), but popular browsers implemented 302 110 | * with the functionality of a 303 See Other. Therefore, HTTP/1.1 added status codes 303 and 307 111 | * to distinguish between the two behaviours. However, some Web applications and frameworks 112 | * use the 302 status code as if it were the 303. 113 | */ 114 | FOUND = 302, 115 | 116 | /** 117 | * SINCE HTTP/1.1 118 | * The response to the request can be found under another URI using a GET method. 119 | * When received in response to a POST (or PUT/DELETE), the client should presume that 120 | * the server has received the data and should issue a redirect with a separate GET message. 121 | */ 122 | SEE_OTHER = 303, 123 | 124 | /** 125 | * Indicates that the resource has not been modified since the version specified by the request headers If-Modified-Since or If-None-Match. 126 | * In such case, there is no need to retransmit the resource since the client still has a previously-downloaded copy. 127 | */ 128 | NOT_MODIFIED = 304, 129 | 130 | /** 131 | * SINCE HTTP/1.1 132 | * The requested resource is available only through a proxy, the address for which is provided in the response. 133 | * Many HTTP clients (such as Mozilla and Internet Explorer) do not correctly handle responses with this status code, primarily for security reasons. 134 | */ 135 | USE_PROXY = 305, 136 | 137 | /** 138 | * No longer used. Originally meant "Subsequent requests should use the specified proxy." 139 | */ 140 | SWITCH_PROXY = 306, 141 | 142 | /** 143 | * SINCE HTTP/1.1 144 | * In this case, the request should be repeated with another URI; however, future requests should still use the original URI. 145 | * In contrast to how 302 was historically implemented, the request method is not allowed to be changed when reissuing the original request. 146 | * For example, a POST request should be repeated using another POST request. 147 | */ 148 | TEMPORARY_REDIRECT = 307, 149 | 150 | /** 151 | * The request and all future requests should be repeated using another URI. 152 | * 307 and 308 parallel the behaviors of 302 and 301, but do not allow the HTTP method to change. 153 | * So, for example, submitting a form to a permanently redirected resource may continue smoothly. 154 | */ 155 | PERMANENT_REDIRECT = 308, 156 | 157 | /** 158 | * The server cannot or will not process the request due to an apparent client error 159 | * (e.g., malformed request syntax, too large size, invalid request message framing, or deceptive request routing). 160 | */ 161 | BAD_REQUEST = 400, 162 | 163 | /** 164 | * Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet 165 | * been provided. The response must include a WWW-Authenticate header field containing a challenge applicable to the 166 | * requested resource. See Basic access authentication and Digest access authentication. 401 semantically means 167 | * "unauthenticated",i.e. the user does not have the necessary credentials. 168 | */ 169 | UNAUTHORIZED = 401, 170 | 171 | /** 172 | * Reserved for future use. The original intention was that this code might be used as part of some form of digital 173 | * cash or micro payment scheme, but that has not happened, and this code is not usually used. 174 | * Google Developers API uses this status if a particular developer has exceeded the daily limit on requests. 175 | */ 176 | PAYMENT_REQUIRED = 402, 177 | 178 | /** 179 | * The request was valid, but the server is refusing action. 180 | * The user might not have the necessary permissions for a resource. 181 | */ 182 | FORBIDDEN = 403, 183 | 184 | /** 185 | * The requested resource could not be found but may be available in the future. 186 | * Subsequent requests by the client are permissible. 187 | */ 188 | NOT_FOUND = 404, 189 | 190 | /** 191 | * A request method is not supported for the requested resource; 192 | * for example, a GET request on a form that requires data to be presented via POST, or a PUT request on a read-only resource. 193 | */ 194 | METHOD_NOT_ALLOWED = 405, 195 | 196 | /** 197 | * The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request. 198 | */ 199 | NOT_ACCEPTABLE = 406, 200 | 201 | /** 202 | * The client must first authenticate itself with the proxy. 203 | */ 204 | PROXY_AUTHENTICATION_REQUIRED = 407, 205 | 206 | /** 207 | * The server timed out waiting for the request. 208 | * According to HTTP specifications: 209 | * "The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time." 210 | */ 211 | REQUEST_TIMEOUT = 408, 212 | 213 | /** 214 | * Indicates that the request could not be processed because of conflict in the request, 215 | * such as an edit conflict between multiple simultaneous updates. 216 | */ 217 | CONFLICT = 409, 218 | 219 | /** 220 | * Indicates that the resource requested is no longer available and will not be available again. 221 | * This should be used when a resource has been intentionally removed and the resource should be purged. 222 | * Upon receiving a 410 status code, the client should not request the resource in the future. 223 | * Clients such as search engines should remove the resource from their indices. 224 | * Most use cases do not require clients and search engines to purge the resource, and a "404 Not Found" may be used instead. 225 | */ 226 | GONE = 410, 227 | 228 | /** 229 | * The request did not specify the length of its content, which is required by the requested resource. 230 | */ 231 | LENGTH_REQUIRED = 411, 232 | 233 | /** 234 | * The server does not meet one of the preconditions that the requester put on the request. 235 | */ 236 | PRECONDITION_FAILED = 412, 237 | 238 | /** 239 | * The request is larger than the server is willing or able to process. Previously called "Request Entity Too Large". 240 | */ 241 | PAYLOAD_TOO_LARGE = 413, 242 | 243 | /** 244 | * The URI provided was too long for the server to process. Often the result of too much data being encoded as a query-string of a GET request, 245 | * in which case it should be converted to a POST request. 246 | * Called "Request-URI Too Long" previously. 247 | */ 248 | URI_TOO_LONG = 414, 249 | 250 | /** 251 | * The request entity has a media type which the server or resource does not support. 252 | * For example, the client uploads an image as image/svg+xml, but the server requires that images use a different format. 253 | */ 254 | UNSUPPORTED_MEDIA_TYPE = 415, 255 | 256 | /** 257 | * The client has asked for a portion of the file (byte serving), but the server cannot supply that portion. 258 | * For example, if the client asked for a part of the file that lies beyond the end of the file. 259 | * Called "Requested Range Not Satisfiable" previously. 260 | */ 261 | RANGE_NOT_SATISFIABLE = 416, 262 | 263 | /** 264 | * The server cannot meet the requirements of the Expect request-header field. 265 | */ 266 | EXPECTATION_FAILED = 417, 267 | 268 | /** 269 | * This code was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol, 270 | * and is not expected to be implemented by actual HTTP servers. The RFC specifies this code should be returned by 271 | * teapots requested to brew coffee. This HTTP status is used as an Easter egg in some websites, including Google.com. 272 | */ 273 | I_AM_A_TEAPOT = 418, 274 | 275 | /** 276 | * The request was directed at a server that is not able to produce a response (for example because a connection reuse). 277 | */ 278 | MISDIRECTED_REQUEST = 421, 279 | 280 | /** 281 | * The request was well-formed but was unable to be followed due to semantic errors. 282 | */ 283 | UNPROCESSABLE_ENTITY = 422, 284 | 285 | /** 286 | * The resource that is being accessed is locked. 287 | */ 288 | LOCKED = 423, 289 | 290 | /** 291 | * The request failed due to failure of a previous request (e.g., a PROPPATCH). 292 | */ 293 | FAILED_DEPENDENCY = 424, 294 | 295 | /** 296 | * The client should switch to a different protocol such as TLS/1.0, given in the Upgrade header field. 297 | */ 298 | UPGRADE_REQUIRED = 426, 299 | 300 | /** 301 | * The origin server requires the request to be conditional. 302 | * Intended to prevent "the 'lost update' problem, where a client 303 | * GETs a resource's state, modifies it, and PUTs it back to the server, 304 | * when meanwhile a third party has modified the state on the server, leading to a conflict." 305 | */ 306 | PRECONDITION_REQUIRED = 428, 307 | 308 | /** 309 | * The user has sent too many requests in a given amount of time. Intended for use with rate-limiting schemes. 310 | */ 311 | TOO_MANY_REQUESTS = 429, 312 | 313 | /** 314 | * The server is unwilling to process the request because either an individual header field, 315 | * or all the header fields collectively, are too large. 316 | */ 317 | REQUEST_HEADER_FIELDS_TOO_LARGE = 431, 318 | 319 | /** 320 | * A server operator has received a legal demand to deny access to a resource or to a set of resources 321 | * that includes the requested resource. The code 451 was chosen as a reference to the novel Fahrenheit 451. 322 | */ 323 | UNAVAILABLE_FOR_LEGAL_REASONS = 451, 324 | 325 | /** 326 | * A generic error message, given when an unexpected condition was encountered and no more specific message is suitable. 327 | */ 328 | INTERNAL_SERVER_ERROR = 500, 329 | 330 | /** 331 | * The server either does not recognize the request method, or it lacks the ability to fulfill the request. 332 | * Usually this implies future availability (e.g., a new feature of a web-service API). 333 | */ 334 | NOT_IMPLEMENTED = 501, 335 | 336 | /** 337 | * The server was acting as a gateway or proxy and received an invalid response from the upstream server. 338 | */ 339 | BAD_GATEWAY = 502, 340 | 341 | /** 342 | * The server is currently unavailable (because it is overloaded or down for maintenance). 343 | * Generally, this is a temporary state. 344 | */ 345 | SERVICE_UNAVAILABLE = 503, 346 | 347 | /** 348 | * The server was acting as a gateway or proxy and did not receive a timely response from the upstream server. 349 | */ 350 | GATEWAY_TIMEOUT = 504, 351 | 352 | /** 353 | * The server does not support the HTTP protocol version used in the request 354 | */ 355 | HTTP_VERSION_NOT_SUPPORTED = 505, 356 | 357 | /** 358 | * Transparent content negotiation for the request results in a circular reference. 359 | */ 360 | VARIANT_ALSO_NEGOTIATES = 506, 361 | 362 | /** 363 | * The server is unable to store the representation needed to complete the request. 364 | */ 365 | INSUFFICIENT_STORAGE = 507, 366 | 367 | /** 368 | * The server detected an infinite loop while processing the request. 369 | */ 370 | LOOP_DETECTED = 508, 371 | 372 | /** 373 | * Further extensions to the request are required for the server to fulfill it. 374 | */ 375 | NOT_EXTENDED = 510, 376 | 377 | /** 378 | * The client needs to authenticate to gain network access. 379 | * Intended for use by intercepting proxies used to control access to the network (e.g., "captive portals" used 380 | * to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot). 381 | */ 382 | NETWORK_AUTHENTICATION_REQUIRED = 511, 383 | } 384 | 385 | export default HttpStatusCodes; 386 | -------------------------------------------------------------------------------- /maestro-checkpoint/workflow-definition.json: -------------------------------------------------------------------------------- 1 | {"workflowName":"Account Registration Flow","workflowDescription":"","accountId":"b0f5ebb5-07a7-4aed-836f-7009793c445d","documentVersion":"1.0.0","schemaVersion":"3.0.0","participants":{"0558869f-5a13-43aa-b42e-62476c273660":{"participantRole":"Account Holder","participantId":"0558869f-5a13-43aa-b42e-62476c273660","participantInfo":{"name":"name_0558869f-5a13-43aa-b42e-62476c273660","email":"email_0558869f-5a13-43aa-b42e-62476c273660"}}},"trigger":{"name":"Get_URL","id":"c30c7afc-7d56-451c-b889-0a6488822fca","input":{"metadata":{"customAttributes":{}},"payload":{"id_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["id"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"dacId_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["dacId"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String","displayName":"Instance ID"},"startDate_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["startDate"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"Date","displayName":"Start Date and Time"},"email_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["email"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"accountHolderName_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["accountHolderName"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"bankName_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["bankName"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"accountNumber_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["accountNumber"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"routingNumber_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["routingNumber"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"}},"participants":{}},"output":{},"type":"API","httpType":"Get"},"variables":{"id_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["id"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"dacId_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["dacId"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String","displayName":"Instance ID"},"startDate_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["startDate"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"Date","displayName":"Start Date and Time"},"email_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["email"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"accountHolderName_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["accountHolderName"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"bankName_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["bankName"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"accountNumber_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["accountNumber"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"routingNumber_c30c7afc-7d56-451c-b889-0a6488822fca":{"source":"step","path":["routingNumber"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"email.value_86115070-acfd-4a50-99bb-42231d020ee0":{"source":"step","propertyName":"email.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Email"},"accountHolderName.value_86115070-acfd-4a50-99bb-42231d020ee0":{"source":"step","propertyName":"accountHolderName.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Account Holder Name"},"bankName.value_86115070-acfd-4a50-99bb-42231d020ee0":{"source":"step","propertyName":"bankName.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Bank Name"},"accountNumber.value_86115070-acfd-4a50-99bb-42231d020ee0":{"source":"step","propertyName":"accountNumber.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Account Number"},"routingNumber.value_86115070-acfd-4a50-99bb-42231d020ee0":{"source":"step","propertyName":"routingNumber.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Routing Number"},"preparedEsignTemplate_9e902136-79ec-4a9d-abb3-2259c11b1d7d":{"source":"step","propertyName":"preparedEsignTemplate","stepId":"9e902136-79ec-4a9d-abb3-2259c11b1d7d","type":"PreparedEsignTemplate","displayName":"Prepared eSignature Template","defaultValue":{"templateId":"b503b21d-9490-4e4d-a29b-b45697f0a6d9"}},"envelopeId_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["envelopeId"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"String","displayName":"Envelope ID"},"status_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["status"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"Enum","displayName":"Envelope Status","enumOptions":["completed","declined","voided"]},"combinedDocumentsBase64_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["combinedDocumentsBase64"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"File","displayName":"Combined Envelope File"},"fields&Account Holder&dateSigned&value_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["fields","Account Holder","dateSigned","value"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"Date","displayName":"dateSigned"},"fields&Account Holder&accountHolderName&value_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["fields","Account Holder","accountHolderName","value"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"String","displayName":"accountHolderName"},"fields&Account Holder&accountNumber&value_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["fields","Account Holder","accountNumber","value"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"String","displayName":"accountNumber"},"fields&Account Holder&bankName&value_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["fields","Account Holder","bankName","value"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"String","displayName":"bankName"},"fields&Account Holder&routingNumber&value_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["fields","Account Holder","routingNumber","value"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"String","displayName":"routingNumber"},"name_0558869f-5a13-43aa-b42e-62476c273660":{"key":"name","type":"String","participantId":"0558869f-5a13-43aa-b42e-62476c273660","displayName":"Account Holder Name","source":"participant"},"email_0558869f-5a13-43aa-b42e-62476c273660":{"key":"email","type":"Email","participantId":"0558869f-5a13-43aa-b42e-62476c273660","displayName":"Account Holder Email","source":"participant"}},"steps":[{"id":"86115070-acfd-4a50-99bb-42231d020ee0","name":"Collect Data with Web Forms","moduleName":"WebForms","configurationProgress":"Completed","type":"DS-WebForms","config":{"webFormSlug":"df37db5b63b5157049189fdb760261a6","webFormId":"237187be-c204-450a-a3e1-b6bca91305d5","webFormName":"Bank Account Details","participantId":"0558869f-5a13-43aa-b42e-62476c273660"},"input":{"email":{"source":"step","path":["email"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"accountHolderName":{"source":"step","path":["accountHolderName"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"bankName":{"source":"step","path":["bankName"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"accountNumber":{"source":"step","path":["accountNumber"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"},"routingNumber":{"source":"step","path":["routingNumber"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String"}},"output":{"email.value_86115070-acfd-4a50-99bb-42231d020ee0":{"source":"step","propertyName":"email.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Email"},"accountHolderName.value_86115070-acfd-4a50-99bb-42231d020ee0":{"source":"step","propertyName":"accountHolderName.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Account Holder Name"},"bankName.value_86115070-acfd-4a50-99bb-42231d020ee0":{"source":"step","propertyName":"bankName.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Bank Name"},"accountNumber.value_86115070-acfd-4a50-99bb-42231d020ee0":{"source":"step","propertyName":"accountNumber.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Account Number"},"routingNumber.value_86115070-acfd-4a50-99bb-42231d020ee0":{"source":"step","propertyName":"routingNumber.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Routing Number"}}},{"id":"9e902136-79ec-4a9d-abb3-2259c11b1d7d","name":"Prepare eSignature Template","moduleName":"PrepareESignTemplate","configurationProgress":"Completed","type":"DS-SignPrepareESignTemplate","config":{"templateId":"b503b21d-9490-4e4d-a29b-b45697f0a6d9"},"input":{"recipients":{"signers":[{"tabs":{"signHereTabs":[{"stampType":"signature","name":"SignHere","tabLabel":"signature","scaleValue":"1","optional":"false","documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"72","yPosition":"386","tabId":"0e52d949-a9cd-4dfa-83f6-d1415b31d77c","templateLocked":"false","templateRequired":"false","tabType":"signhere","agreementAttributeLocked":"false"}],"dateSignedTabs":[{"name":"DateSigned","value":"","tabLabel":"dateSigned","font":"arial","bold":"false","italic":"false","underline":"false","fontColor":"black","fontSize":"size9","localePolicy":{},"documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"337","yPosition":"403","width":"0","height":"0","tabId":"49ed1de8-7c9a-4d9a-915f-61a1e51d529a","templateLocked":"false","templateRequired":"false","tabType":"datesigned","agreementAttributeLocked":"false"}],"textTabs":[{"validationPattern":"","validationMessage":"","requireInitialOnSharedChange":"false","requireAll":"false","name":"Account Holder Name","value":{"source":"step","propertyName":"accountHolderName.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Account Holder Name"},"originalValue":"","required":"true","locked":"false","concealValueOnDocument":"false","disableAutoSize":"false","maxLength":"4000","tabLabel":"accountHolderName","font":"arial","bold":"false","italic":"false","underline":"false","fontColor":"black","fontSize":"size9","localePolicy":{},"documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"210","yPosition":"170","width":"366","height":"19","tabId":"b2f7392e-f130-42ca-90a0-b7f84b31cf44","templateLocked":"false","templateRequired":"false","mergeFieldXml":"{\"admBindings\":[{\"fqn\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0.BankAccountOpening\",\"path\":\"$.accountHolderName\",\"position\":\"0\"}]}{\"folder\":\"BankAccountOpening\",\"folderProperty\":\"Account Holder Name\",\"initialValue\":\"accountHolderName\",\"name\":\"Account Holder Name\",\"legacyPath\":\"$.BankAccountOpening[0].accountHolderName\",\"required\":true,\"type\":\"martiniDataTabs\",\"collectionItems\":{\"0\":\"BankAccountOpening 1\"},\"modelType\":\"data-verification\",\"namespace\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0\"}{}{}","tabType":"text","tooltip":"Account Holder Name","extensionData":{"extensionGroupId":"a9084b3e-4147-45fb-b985-c354dded21a3","publisherName":"John Doe","applicationId":"a0833a82-3682-4555-bd64-61172372adfe","applicationName":"Bank Account Opening","actionName":"","actionContract":"","extensionName":"","requiredForExtension":true,"actionInputKey":"accountHolderName","extensionPolicy":"MustVerifyToSign","connectedFieldsData":{"typeSystemNamespace":"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0","typeName":"BankAccountOpening","supportedOperation":"verify","supportedUri":"/connected-data/v1/connected-objects/com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0/BankAccountOpening/verify","propertyName":"accountHolderName"}},"agreementAttributeLocked":"false"},{"validationPattern":"^[0-9a-zA-Z]+$","validationMessage":"Invalid validation for accountNumber","shared":"false","requireInitialOnSharedChange":"false","requireAll":"false","name":"Account Number","value":{"source":"step","propertyName":"accountNumber.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Account Number"},"originalValue":"","required":"true","locked":"false","concealValueOnDocument":"false","disableAutoSize":"false","maxLength":"4000","tabLabel":"accountNumber","font":"arial","bold":"false","italic":"false","underline":"false","fontColor":"black","fontSize":"size9","localePolicy":{},"documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"210","yPosition":"243","width":"366","height":"19","tabId":"1f3e583e-3548-4622-a454-7354854d9b7f","templateLocked":"false","templateRequired":"false","mergeFieldXml":"{\"admBindings\":[{\"fqn\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0.BankAccountOpening\",\"path\":\"$.accountNumber\",\"position\":\"0\"}]}{\"folder\":\"BankAccountOpening\",\"folderProperty\":\"Account Number\",\"initialValue\":\"accountNumber\",\"name\":\"Account Number\",\"legacyPath\":\"$.BankAccountOpening[0].accountNumber\",\"required\":true,\"type\":\"martiniDataTabs\",\"collectionItems\":{\"0\":\"BankAccountOpening 1\"},\"modelType\":\"data-verification\",\"namespace\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0\"}{}{}","tabType":"text","tooltip":"Account Number","extensionData":{"extensionGroupId":"a9084b3e-4147-45fb-b985-c354dded21a3","publisherName":"John Doe","applicationId":"a0833a82-3682-4555-bd64-61172372adfe","applicationName":"Bank Account Opening","actionName":"","actionContract":"","extensionName":"","requiredForExtension":true,"actionInputKey":"accountNumber","extensionPolicy":"MustVerifyToSign","connectedFieldsData":{"typeSystemNamespace":"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0","typeName":"BankAccountOpening","supportedOperation":"verify","supportedUri":"/connected-data/v1/connected-objects/com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0/BankAccountOpening/verify","propertyName":"accountNumber"}},"agreementAttributeLocked":"false"},{"validationPattern":"","validationMessage":"","shared":"false","requireInitialOnSharedChange":"false","requireAll":"false","name":"Bank Name","value":{"source":"step","propertyName":"bankName.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Bank Name"},"originalValue":"","required":"true","locked":"false","concealValueOnDocument":"false","disableAutoSize":"false","maxLength":"4000","tabLabel":"bankName","font":"arial","bold":"false","italic":"false","underline":"false","fontColor":"black","fontSize":"size9","localePolicy":{},"documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"210","yPosition":"207","width":"366","height":"19","tabId":"b7422ba2-f941-48ec-bc5f-0dc006d51745","templateLocked":"false","templateRequired":"false","mergeFieldXml":"{\"admBindings\":[{\"fqn\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0.BankAccountOpening\",\"path\":\"$.bankName\",\"position\":\"0\"}]}{\"folder\":\"BankAccountOpening\",\"folderProperty\":\"Bank Name\",\"initialValue\":\"bankName\",\"name\":\"Bank Name\",\"legacyPath\":\"$.BankAccountOpening[0].bankName\",\"required\":true,\"type\":\"martiniDataTabs\",\"collectionItems\":{\"0\":\"BankAccountOpening 1\"},\"modelType\":\"data-verification\",\"namespace\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0\"}{}{}","tabType":"text","tooltip":"Bank Name","extensionData":{"extensionGroupId":"a9084b3e-4147-45fb-b985-c354dded21a3","publisherName":"John Doe","applicationId":"a0833a82-3682-4555-bd64-61172372adfe","applicationName":"Bank Account Opening","actionName":"","actionContract":"","extensionName":"","requiredForExtension":true,"actionInputKey":"bankName","extensionPolicy":"MustVerifyToSign","connectedFieldsData":{"typeSystemNamespace":"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0","typeName":"BankAccountOpening","supportedOperation":"verify","supportedUri":"/connected-data/v1/connected-objects/com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0/BankAccountOpening/verify","propertyName":"bankName"}},"agreementAttributeLocked":"false"},{"validationPattern":"^\\d{9}$","validationMessage":"Invalid validation for routingNumber","shared":"false","requireInitialOnSharedChange":"false","requireAll":"false","name":"Routing Number","value":{"source":"step","propertyName":"routingNumber.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Routing Number"},"originalValue":"","required":"true","locked":"false","concealValueOnDocument":"false","disableAutoSize":"false","maxLength":"4000","tabLabel":"routingNumber","font":"arial","bold":"false","italic":"false","underline":"false","fontColor":"black","fontSize":"size9","localePolicy":{},"documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"210","yPosition":"281","width":"364","height":"19","tabId":"fda0e852-0068-4156-9e99-305f353bf084","templateLocked":"false","templateRequired":"false","mergeFieldXml":"{\"admBindings\":[{\"fqn\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0.BankAccountOpening\",\"path\":\"$.routingNumber\",\"position\":\"0\"}]}{\"folder\":\"BankAccountOpening\",\"folderProperty\":\"Routing Number\",\"initialValue\":\"routingNumber\",\"name\":\"Routing Number\",\"legacyPath\":\"$.BankAccountOpening[0].routingNumber\",\"required\":true,\"type\":\"martiniDataTabs\",\"collectionItems\":{\"0\":\"BankAccountOpening 1\"},\"modelType\":\"data-verification\",\"namespace\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0\"}{}{}","tabType":"text","tooltip":"Routing Number","extensionData":{"extensionGroupId":"a9084b3e-4147-45fb-b985-c354dded21a3","publisherName":"John Doe","applicationId":"a0833a82-3682-4555-bd64-61172372adfe","applicationName":"Bank Account Opening","actionName":"","actionContract":"","extensionName":"","requiredForExtension":true,"actionInputKey":"routingNumber","extensionPolicy":"MustVerifyToSign","connectedFieldsData":{"typeSystemNamespace":"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0","typeName":"BankAccountOpening","supportedOperation":"verify","supportedUri":"/connected-data/v1/connected-objects/com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0/BankAccountOpening/verify","propertyName":"routingNumber"}},"agreementAttributeLocked":"false"}]},"recipientId":"79452210","roleName":"Account Holder"}],"carbonCopies":[],"certifiedDeliveries":[]}},"output":{"preparedEsignTemplate_9e902136-79ec-4a9d-abb3-2259c11b1d7d":{"source":"step","propertyName":"preparedEsignTemplate","stepId":"9e902136-79ec-4a9d-abb3-2259c11b1d7d","type":"PreparedEsignTemplate","displayName":"Prepared eSignature Template","defaultValue":{"templateId":"b503b21d-9490-4e4d-a29b-b45697f0a6d9"}}}},{"id":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","name":"Send Documents for Signature","moduleName":"SendDocumentsForSignature","configurationProgress":"Completed","type":"DS-SignSendDocumentsForSignature","config":{"participantId":"0558869f-5a13-43aa-b42e-62476c273660"},"input":{"isEmbeddedSign":true,"preparedTemplates":[{"preparedTemplateMetadata":{"source":"step","propertyName":"preparedEsignTemplate","stepId":"9e902136-79ec-4a9d-abb3-2259c11b1d7d","type":"PreparedEsignTemplate","displayName":"Prepared eSignature Template","defaultValue":{"templateId":"b503b21d-9490-4e4d-a29b-b45697f0a6d9"}},"customFields":{"textCustomFields":[],"listCustomFields":[]}}],"emailSubject":"Complete with Docusign: Account Registration Form - DocuCo.pdf","emailBlurb":"Please complete this account registration form.","recipients":{"signers":[{"recipientId":"79452210","name":{"key":"name","type":"String","participantId":"0558869f-5a13-43aa-b42e-62476c273660","displayName":"Account Holder Name","source":"participant"},"email":{"key":"email","type":"Email","participantId":"0558869f-5a13-43aa-b42e-62476c273660","displayName":"Account Holder Email","source":"participant"},"routingOrder":"1","participantId":"0558869f-5a13-43aa-b42e-62476c273660","roleName":"Account Holder","clientUserId":"1"}],"carbonCopies":[],"certifiedDeliveries":[]}},"output":{"envelopeId_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["envelopeId"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"String","displayName":"Envelope ID"},"status_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["status"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"Enum","displayName":"Envelope Status","enumOptions":["completed","declined","voided"]},"combinedDocumentsBase64_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["combinedDocumentsBase64"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"File","displayName":"Combined Envelope File"},"fields&Account Holder&dateSigned&value_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["fields","Account Holder","dateSigned","value"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"Date","displayName":"dateSigned"},"fields&Account Holder&accountHolderName&value_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["fields","Account Holder","accountHolderName","value"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"String","displayName":"accountHolderName"},"fields&Account Holder&accountNumber&value_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["fields","Account Holder","accountNumber","value"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"String","displayName":"accountNumber"},"fields&Account Holder&bankName&value_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["fields","Account Holder","bankName","value"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"String","displayName":"bankName"},"fields&Account Holder&routingNumber&value_28f13fac-6cfd-40bd-8081-858aa3fb1a60":{"source":"step","path":["fields","Account Holder","routingNumber","value"],"stepId":"28f13fac-6cfd-40bd-8081-858aa3fb1a60","type":"String","displayName":"routingNumber"}},"participants":{"0558869f-5a13-43aa-b42e-62476c273660":{"name":{"source":"step","propertyName":"accountHolderName.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Account Holder Name"},"email":{"source":"step","propertyName":"email.value","stepId":"86115070-acfd-4a50-99bb-42231d020ee0","type":"String","displayName":"Email"}}}},{"id":"5a340f6d-76bd-4121-beb3-d12da2b4ad0c","name":"Show a Confirmation Screen","moduleName":"ShowConfirmationScreen","configurationProgress":"Completed","type":"DS-ShowScreenStep","config":{"participantId":"0558869f-5a13-43aa-b42e-62476c273660"},"input":{"httpType":"Post","payload":{"participantId":"0558869f-5a13-43aa-b42e-62476c273660","confirmationMessage":{"title":"Account Registration Submitted","description":"Thank you for submitting the Account Registration form. Please inform us if you want to withdraw this in the future."}}},"output":{}},{"name":"Add a Path End","id":"5449a681-34c7-4aa6-8059-0cb6b6dd5131","moduleName":"End","configurationProgress":"NotStarted","type":"DS-End","config":{},"input":{},"output":{}}],"instanceName":[{"source":"step","path":["startDate"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"Date","displayName":"Start Date and Time"},{"source":"step","path":["dacId"],"stepId":"c30c7afc-7d56-451c-b889-0a6488822fca","type":"String","displayName":"Instance ID"}]} -------------------------------------------------------------------------------- /maestro-checkpoint/esign-template.json: -------------------------------------------------------------------------------- 1 | {"templateId":"b503b21d-9490-4e4d-a29b-b45697f0a6d9","uri":"/templates/b503b21d-9490-4e4d-a29b-b45697f0a6d9","name":"New Account Registration","shared":"false","passwordProtected":"false","description":"Form to create a new account","created":"2025-10-26T22:45:14.1230000Z","lastModified":"2025-10-26T22:52:55.1800000Z","lastModifiedBy":{"userName":"Rob","userId":"c47f9df9-8cc1-468d-ba9b-0ef93d7e6dfc","email":"rob@thisdot.co","uri":"/users/c47f9df9-8cc1-468d-ba9b-0ef93d7e6dfc"},"lastUsed":"2025-10-26T23:24:22.5870000Z","owner":{"userName":"Rob","userId":"c47f9df9-8cc1-468d-ba9b-0ef93d7e6dfc","email":"rob@thisdot.co"},"pageCount":"1","folderId":"afce90e6-e121-4da1-b18b-cbf35949a3fb","folderName":"Templates","folderIds":["afce90e6-e121-4da1-b18b-cbf35949a3fb"],"autoMatch":"true","autoMatchSpecifiedByUser":"false","documents":[{"documentId":"1","uri":"/envelopes/b503b21d-9490-4e4d-a29b-b45697f0a6d9/documents/1","name":"Account Registration Form - DocuCo.pdf","order":"1","pages":"1","documentBase64":"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ICA8cmRmOkRlc2NyaXB0aW9uIHhtbG5zOnBkZj0iaHR0cDovL25zLmFkb2JlLmNvbS9wZGYvMS4zLyIgcmRmOmFib3V0PSIiPg0KICAgICAgPHBkZjpQcm9kdWNlcj5Eb2N1c2lnbiBETXYxMDwvcGRmOlByb2R1Y2VyPg0KICAgICAgPHBkZjpQREZWZXJzaW9uPjEuNTwvcGRmOlBERlZlcnNpb24+DQogICAgPC9yZGY6RGVzY3JpcHRpb24+DQogICAgPHJkZjpEZXNjcmlwdGlvbiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHJkZjphYm91dD0iIj4NCiAgICAgIDx4bXA6Q3JlYXRlRGF0ZT4yMDI1LTEwLTI2VDE1OjUyOjU1LTA3OjAwPC94bXA6Q3JlYXRlRGF0ZT4NCiAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDI1LTEwLTI2VDE1OjUyOjU1LTA3OjAwPC94bXA6TW9kaWZ5RGF0ZT4NCiAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjUtMTAtMjZUMTU6NTI6NTUtMDc6MDA8L3htcDpNZXRhZGF0YURhdGU+DQogICAgPC9yZGY6RGVzY3JpcHRpb24+DQogICAgPHJkZjpEZXNjcmlwdGlvbiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHJkZjphYm91dD0iIj4NCiAgICAgIDxkYzpjcmVhdG9yPg0KICAgICAgICA8cmRmOlNlcSAvPg0KICAgICAgPC9kYzpjcmVhdG9yPg0KICAgICAgPGRjOnRpdGxlPg0KICAgICAgICA8cmRmOkFsdD4NCiAgICAgICAgICA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPkFjY291bnQgUmVnaXN0cmF0aW9uIEZvcm0gLSBEb2N1Q288L3JkZjpsaT4NCiAgICAgICAgPC9yZGY6QWx0Pg0KICAgICAgPC9kYzp0aXRsZT4NCiAgICAgIDxkYzpmb3JtYXQ+YXBwbGljYXRpb24vcGRmPC9kYzpmb3JtYXQ+DQogICAgPC9yZGY6RGVzY3JpcHRpb24+DQogIDwvcmRmOlJERj4NCjwveDp4bXBtZXRhPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3hwYWNrZXQgZW5kPSJ3Ij8+CmVuZHN0cmVhbQplbmRvYmoKNzMgMCBvYmoKPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aDEgMjEwOTYvTGVuZ3RoIDEzNTgyPj5zdHJlYW0KeJylfAl4U1UW8L33bcnL9pK22ZomL02bQlO2tlAKlb4CBbWyQ2ywlSIgm8hSVFSQ4gZWFHTGdRxFxwUXJF2AsCiMoo4oAzM6zogLODKKjlVmhsGNNv+5N3klHZ3/m//7k5x7z7v3vLud5Z5z32sRRggZUQvikLJg3uy5yz8deDeUPAIwbAEUOMoMnwP+LkDBVUvnzEbkWCfg3wGsXjJ71TJhk/FRhPBKuFbnXLtSfe72D6+G618iJM5ctmLesruCXTUISacRMn0+/6rrr7zukwdyEcr6CzQ/fcGSlatWTzDfjNDFJXD/qiuXzV/y5r5jAlw/Cff8lo1N/PTPPfW2l2bZqv5tyDWg//z8sL17voIMU9gsMLsD0VQa1TMRjVGg/ocbFJQuP//xp/Or0gBzIjAnHkhFuDZsQUg+ipAZymzlACcQcmwAOIlQzkaEXAcQ8kxGyFuFUG42Qj64x38GoaAPodCtCBXC+hUVINR/MEKRBQgNgPUZ8hVCZe/SebPR+MkOVIUOIQkRpKBBKAa97xe+QgIiwh7kAfAKzyAPH0ZuhJLAg+QpmvcsTJ6i9TQnX0I7iTQgtBVtwwvRNrQfvYJPw13b0W6Y1++QC40Ffq5Gv0TrkYhmQskdaCp8BSj/JfYkO6H3x4H/j6PDQHspugntQU7sTn6B1qLbuHfgrtuQBeWjGjQZLUV34UuS16AGdJy/BVWgS9DVaBluSdYn707em3wSPYV2c79LdiMT8qI58D2c/Fr4S/JDNADuuA89hI7je407kAa9tADlr9EK9DDXyOPk/OQPMIIgug7GwKMJ6DA+QCLQ+jz0OXbj1dwYaOU3yXjyIFD5UCNagB5Ge/BQPJ4EhYbkhORh5IQ+VkGrD6F2tBO+CfQSOobNwunkk8nTyINK0EUwn070e3yA6+le11MNKybAKvVHlVCzFL2M3kBHcQj/liwVzEKpoAk3JN9F2WgImgGjfQbu/Ax/S26C71rudX5ccjSywrrcQ1cbvYY+wV48CE/CUdKfLCWPciuQAXocAt+5aCGs94PQ+sc4gncSMznC/YZ/nv9RzOs5kbQCR8LoV+jX6LfYAjNVcTO+Gb+HPyVjyCzyK/JX7pf8s/wfpdkw68vREnQXeh59ix14OJ6CL8ML8Gq8Ht+DH8KH8VF8itSQ6WQx+YZbwC3nXuJHw3ca38zfItwu3Cme6qnvOdjzh55vk6XJ29EUkId1MPr70KMws93oCHofvsfRX7GATdgKXxUH8Qx8I3xvwnfhJ/BW/CzuhF6O4r/iL/A/8b/xjwREl4gklwRJPnxDZAW5jvySPEKOwPco+Yp8z7m4fC7CDeWquBi3FEa1ntsM3x3cJ7yXP8InYZ1LhfuFx4StwvPCK8Jp0SzdbECGt8/9pru4++Me1LOh5/6e9p7O5CcoB3johVUIgNZMQbPhuwj4fT9I3Hb0DjbD2nlxMR6FL4GVmYUX4eV4Fazkrfhh/BQb+4t4H6zSn/E3MGYL8bExDyRDyWgyCb6Xk3lkOdlM7iWd5D3yAydxJs7G5XDF3HiukZvHreSu5+7n4tzb3EfcX7mz3Dn4JnmZD/D5fJiP8OP5Wfw1/KP85/znQoPwlvA3URaXiLeLCfEf0jBplDRZmiI1SpukndK7hiaQzlfRDrQr0yDhE9w6rpbbge4mZbyH/J78HuR5FprLTSAgqWQr3kDW4E5SIKwSR5KReCI6zYdhrV8nj5GzZCQ3AdfhaWgRGZJqTczmn4Osin8VdfH7YG6/h5ZXiWZ8E/lGNKN2jEgl9PkaN5iPcG+hY9xxLPGPow94GbtwF3mGmwxS8BI/SqhHQe4R9CK3HK9BO0gtWMUfDRtBjifi58AuTMel+DsuiTgyEaSogvsU3YIWk7+gLtDjDegBPJefj+5GZXg1+hw9DVrRX7haLBZz8JtkId9KsnAnIvyzMLtKXIA5IRvdihu5h8VvyPvoGnSEl9HH3Asw+iPkRW4Cf1qYiheABqxBt6PlyXXoeqGe/yOejzgcRYX8CbBuq7lSPgj5WrAqDWDTdoJ27wE7UMNNgBI3SM4lIBczwEI8DN8HwU7wIEELQccvBSv2e9QpTicJNF+wYrA6YI3f6pmKZiafRg8l56Ork/eiAWAP1idXQ4tb0d/QJrQV39ZzI1oGe8n7oNuXCOPIEWFccgBpJe+TaeT+vvyF1S7EbvQlfF+Ei1HCXtTK/xlNQ9XJjck/gXT3Awv7ELoCXYxOwiy/hh4u5A6gsp6JpC05jlsG8z2OpiSfSQawjBYkr0KT0D70lCSg2VIEeBzHf4T53ojmkanJldy8noWwDptgFTRYrWvA/tzBL+dv4b9HqMaMpnMl9EvyUR4KgHYWg0YFuOJ2MS+Q4Pp1hN2Bo/u4/ugEAOH6t0fyAru5Ii6vfWRAS3ChDkdOqa1mAKfCLjaIpSqkSwG2A+wH4NEszg/lCqRrAVoAtgPsBzgKICIEKa1VAZYCPAZwgtZweZyvXQ0oNUWcB+71gIGxcS70DUASgINxuqBXF5oEMAtgE8BjACKjoyVLAdYC7Ac4zWo0ztV+bxmM3dV+J8s6Fl1Vyi5npy4bGtllx6WxVD5hSiofe1GKbESKbEh5qnjg6FReVJLKHYWlLTSXLaUHapycEybphIEvgxSTg8iGMYjeFi4HxQEIJ6ZLNM7RURAufWw/xyPMEQ7DVhFIHuBwu8VeWiOTJPkGOVCAfE26UjWkq8NqL32s5mLyV7QdYD8AR/4K30/IJ2gtOUHXHNJqgMcA9gMcAfgGQCQn4Hscvh+Tj5GNfIQGAVQDzAJ4DGA/wDcAEvkIUoV8SL0UllK8GoCQDyFVyAcwrQ8gtZFjgB0jx2Bo77RXVJbuZkhkUBoJFKYRV24acThLE+SP7d/3B4kKA6dBovZy+WgUKuPy2wuHgPi526sWBhLk0w41EthSM5i8i+IABEbyLvT8LlIBJgM0ASwDEAF7D7D3UAvAZoAtAHEAkDJIFQCVHAJ4G+A9NBhAA5gMYCBH26GbBDnSHh4dqHGC0X0DHKAAOUx+x/K3yessf4u8xvI3IfdDfoi83u4PoBoT1CO4R4FcgXwQ1Avktx0FjkCyxk72w9oFIB0EUA0wCWAWwCYAkewn+e1zAw5oZC86BH5tgLSjL1j+NHrCgLRFAS08BgRQpUl4xAWAQfKY+liYaOH7H4JLmoTvvhcwmoRv3QgYTcI3rAOMJuGrrgWMJuG5iwCjSXjmLMBoEp40HTBIEuTRXQVFgYpJi7FaYyPXwSpdB6t0HazSdYiHPR2+6Hueju1X7cXFsGIPa5H+xYGWPbhlH26ZiluewC3zcMtNuGUdbqnCLZfjlghu8eEWP27RcMtePByWogVrnX0uKzU3bjmEW7bhlmbcEsYthbilALeouEJLkGD7RWUsq2VZRw1VOsgvGAXWx0aCsKJBkPkg2IT9kB4BSLIrDYjU/BSxx0/z/I7i6tT1wBGlS0F9XoUbXwU2vIqOA/DAoFdBjF6FRl6FBmyQVgPMAjgA8A1AEkAE6nwY+CaW2iAdBFANMAtgLcA3ACIbzjcABC1ND3E7Gxgd9KD0wCcB8ORV+FLHKUiCWp7iUyLKhdwmH7b58SR/0k8qkNMJW4XDbrAnsGXnt5bvvrUgY42R3E02UdMN7koq39T+PZhu/GB7eG+gJgc/gPw8SB6uRGFcCPlw1MyuhyKfgeblyEeeh7y03ReF22zt4ZLAHmyld+0MfO87GfjClyCAnvLtDfxZTfC4PfAnKHl+Z+Bd3x2BNwclDFCyL5zAkO1RGelu3/DAtkOMdB1UPNweuIlmOwNrfOMDi32sYl6q4vJmuNJsganhmYELob2xvisCWjO0uTNQ7bs8UJWiGkrv2RkYDEOIpNBiGGx/H+s05GcNzqhI4AVaiXS/VC9NAi+rVCqRglJAypNypWyDw6AYrAazQTYYDKKBNxDwK7MTyRNahEaD2SILCkWepjzDFUJTkgofCTYQ2IrjWVwdqZs2GtfFD8xBdVeo8bPTQgksT5kZF0KjcdxRh+qmj44Pj9QlpOTUeEWkLi5Nvqy+DeO7Y1AaJxsSGE2vT+AkLbotN+4YU78bYWy/7a5cmve77a5YDLmd11a7qx2j7JXjxv5M0pROI+c/7j54Xvz+umn18efyYvFSiiTzYnXxX0xTG+p3g6N+unbsbvwPmsXqd3Oj8D9rp9JybtTYWKwugaOMDqn4H0AHEvMPRmeAzZnSIdXgT9E9nKIrhPuBroBmQGc0okJGV2g0MjoeU7q25oLasW0FBYzGpaJmRtPsUjNpDhUCTWEho3G2oEOM5pCzhdLERzESnw9I/D5GgsH7ZyQ+7GUk0fMkg9Ikd/SS3MF64vB5Gl+KxnJCp7GcAJrI//qZNzoSwR0jY3MaaueFaptCtfMAmuJ3XrvAHW+5QlXb5sRohRrnwk1XzFlA89nz4rHQvLHxOaGxatvIhp+pbqDVI0Nj21BD7fT6tgZt3tj2kdrI2tDssbGO8ZPLK/r0dUdvX+WTf6axybSxctrX+Iqfqa6g1eNpXxW0rwra13htPOsLMRmfXN9mQKNjYxpSeQcxySCvTbnB2GinsmwUE96RQfdNuXvAY9mKTJFY3BwaHbcA0KoBNQNqaBXoFK2yQrEtXeW+aWQwdw/emq5SoNgeGo0iK69pvga5axeOTf2a4QNFK6+hC55KI83/7QN1tXFt9tjmlQjVxYun1cWrp8ysb5MkKG2iU4qP0MtMptpE8kCqcCAUjqCFHNdLSMuqaJnRmCb8Kf+vSedjqBa0kL0dWPPjlag5xsX9ddMJmILpM2GuDTPr94A/RbeI5hhMsBmCpWa9jfSwIxGUukZ0zjqsvCaNpddiZTpP3Qm3NOtL0vuhixXpXbGVrFm2nBFqwdgBhwDONpLQ6E6CT4pSgjykZSGBP8khWeJPYuQxiMJJwu2DwNGIH8IDkTuinK3qrpqonKma0F2FqgFXzkEyZHDQHrQXQgL2Ep1TuQPnNAH9iFT+ADWYNThBFpEl0FeJ5llGlnFkAp5ACA4h4hWWAYGHX3aXOzJROdmofIYGTegaMhgtx41ZQ4M5NaQ/TuzYQUMkgmYkP+ftwgGkoDz8URshY6bXa7LXzwvZfovFZUwkT3XabGQGRTSPxQKYHZlpCXKazZCaaRkaBOtwGJLDqLqrGrrKbRN/2tIZaEmkLX3WabEw5GvNYzKJtEmFliDFbKYpLett8nyb2kReXE82mDbY3rQKRsnkJrVZl+Rc7BmTOz2rIafBMzV3sbTYNCfrqpzFnqbc68l14rWmG2zrxQel+5U33cfIe+J7pg9s3t4h1SjJM8iMzFhDUeRK/hOZkCmNf4csyII1zR51NRu1YKh8sBEjo2IkxhoZbtIJjclTKcJdUePmgN1sNifA54rarSZTCjFYLIB0RO3NCMRcM0NLKoSIBOmkyJAmRSnSnVG02f/GnVQoYOqNkS5IKdq4nKHppcCNy1FjnIyJa5PrO0XVo/gSydPtRDW9nDyBnAAOABvAcPrBALFYLEtxDCsrdTodOQoRQ/lF4SzFWVY6zK6EQ/mSOGPxO1uubV85etE7j797/T27n129+tlnb1p9cSN5B/P4ghdmdfQkj/X09Ly67cFd+Nc9D3xzGi/Ai75eeDuVxeMgSD+CDMnoqw65d2Y6IuurgXRETs21d9JaMMppFnv5Yn4t2UQeMvAv8NiIRIFwRgGbCT4ks9WTKR8QphEwuBWdigKCl0h+qdmZOPqYOFqZOMJqaB4qbLpEMenymgXNYisXaFtW2paAVUETiOAx7cFV+DaUUpflqRVnH7hIaWW1qxLbK+nKo8YITlUGQ3ZRlIYOG1ZRRn7srHln+gN/HbSSv3HU6sCL4w/NglFWIcRLsC5+/G1aH4x2xeLOyhJnWKg62O0M+VozKgpg/mzBT9XMRQn8flrr91mhxm+m4/cnyF7NTGSXC+J1OyFqwO6oHPTuYZoeRoOoeESqaXqwlCog6e3Q7HAQ1qFmtNmJ3s8JzeTIIjP82bSMtt0OTVN1N5nIDEC+0tha/lxvVCdpf7Q31pk2fqQwUtwr7Bf3Sm8Y3vRJF5lj5unWxea51hscN2Td4djn+Jv3b7mnveb9pl1ZxC8rBlE85PNm+3xeg8/LYWLw+jiLX0mQJzsm2TG43+4ddJyIDqwDE7PcR1nlDGWVe5XVEpWbXe+AQFKFxXvJOqQiBQ/XzPYd1WQWWUrWEp7sIQXgiW9qYyrWeKYLWF2lnEnpFljd6q7uxpN2B+U2JOutAyPWNcpBuADepxVOM+ZC6JCn+BXx5eRpJIGaGSA3AujaNjyGGnHjilisMCcYrgABGTZsaDmomSgVDaM6mJMNggM/XjpXQVyFv3n4m60P3XjzI3h31nd/eOfshc+88kSDf9u2mqo5B246+LcrF//ikdasI+9/ua3+uX1Pbpg9hDnM0eRnvBNkK4Lb06w2edwa5ZjbhzAV8YgZLnD/kGyxmW1+We6f4/fx/v4+ob8lZDG7PRg5VIUqjSqFKd8peXgQtbmHB9EvclRWVytdShdwvOt15XVHpXIwUkqBcnywYHFaai23W/ha+6X2a3O5qc6rlEXZc53XWK7Pvt3Smn1H7lMW2WS2WHkJQ3+YslaDge/F9BGABQ/tNJtzePce8iTykAWaEUYnwPAsjj6cdmRw2pFhlh3Ns9SlKlHdVDPUFqnPTVLGTVLGTVJzmNnyMEZhJUxg1md20fvDmwe4E3h4u+cdvAeCNwSLZ+q11JtLEvjetLhEupjApI3xmUhjr03uPkkVo0th0pMSnl6BaRdUDvQNBCNGzQdeHsuqcFLTy2RCquhFdfGg8iHRFIXyw9HOwH2L125/Yk3ZJdkOU3Pi9kULN2Z3Br98cdWhxVfOvXlzz6n3fpvEt7gfWh+/efXj2Y+SVWvm3HzrreqON+a3z531yED/S3cf6Pn3Z3Sv99LnbcIesNMW/K99yJz8IbVknVGLmDbWgm61RR0x9tpxHRF0Oy7qiLHXsuuIZEgTG3RE0nc6g6GXJr0NGHRE0BFRR4w6kt4ztIqoo968wPyw+Vnzm2bhEu4Syy95zgEGBJlFThJkEyfBzmOxHOL4bI7jOQsiZgsvcXvJXmQAH22LJiOeBxJ0SOYT5MpdgiBreYFyWd9S5JR/wpCvmaMiJ3CFZpG0/FC51BIcKm22EapfJkt2OSIKUQlH6M30HkBO7qT3kB3WBN7IxOYruo/THeUMtdBVymcK21DA3ztbZa+kslJZuX5ghAc7Y7PZYIthDq8l+XG7oxKs9ruaqaySyx9QyfF5eVW0iRgIEdBo2WbNVGlumVxp1sKV5nwf5AMq2c4Uwz8TT6EI+JJDcZm9LCdk5+yY3N99K/n1L15/vbNnKJ71FLfz3MVP9TwOJvK+7sWpZ7rUNwwKT8P+9WpHls59h45kmdN8dOhIljnNLAcgu6n6pUwTBN6wXha6QNhnlf05OT4H3cxMNp73+yxWjCQ3bOTM0WQIM2N0m6FmiKoX6Fb3QTA91PKUO9h2aGNpnff6vNa8+7OeyXrV/J75g1yDMcttLfZyWXKOIyvrkNWWbc3KttosYH20LNq1Zt1iJVarTcvB6WHssvH4HWqZYNPR7HRA9lnKUmWtsknhlf/ZsriZZXFj5FbcxK1bFvdm1bEPD0U2fB9QDm+37vg5CxPoa2H62JhGkBW6J7E1aLQDgEk+ud4wMCKAwKDMjanTOFgYbNoD+xHHrA21N8sbQRpS/M80OmBpsoI5QQ6sDcrJlsAdDM94Keehq27u3Lbx0o39nr2bvN+9a9Kt9xzAhpV3nfldN25RWu88+MTD7ZOqneQfL/Rc29Bz9g9v3NN+gsUQE0BOcmAvykPFvbtRwIYDeBbmcG4/v2bBFgs4HblCvj/bIvsxKlSoO8LiCcXvUijjXWwvcrF4wpV2/g+/e1h5TReAxi7lYCMVgAGLPXispOWM9YxVZzqmq4u5udJcwyLHXHWl4RrfbYbbfe8Z3nXaJZVyoCilmuKMEHV5cikWZBV0WJMtBAaWi9+h3lqC7kL6IDHdD9COwj7cL8zgfmEG9wubFcZ9BSMFTAjM7fQu6ncqm0vAdgzv8Osq49fNox+s2V7Wjh9XapZq1yzXUtdaF+9S0gSwGszcWaMuJ23K5aRjdiVIQUekNzxI7T+Z0tKV2ozYJgQL1isau6mb0lmkhtRgQpcN2gDdj2JYChexGECU6PbjoN5JKB/ZlQq6GeHsDLHhfuxwl1y0OFoz4wpSs29+Z/d1R2/9pOfkr+84te2j7opJd09c8eQTN97wHD/NumjwhMGjvv5wTlPPt39s7boJ1+HV+Nnfbn3l3EeNz8USjz64fXvKxsyGPckpPANruUyzHrRgHn7EwBvBcFMTMZhg3mi2NHMcoUs8iflxHPHaDM3Gv6NJIGGzCFcN2VK8FgIVjzWtShBONy6vmnCma6JylvrwCqwM9e8q7ZUpZw40g8bCIuJEKTTM4aiYze3Y2NNVN8y2m7v5X3fwP2zbeF+Po+fHxAfb8Jf4jUf0WNlD/XlUTEIpj36XKQA6X2gHjT/Lwluq+kze3DQI6Ud557YzU2VnsYjdbS+JmPr5bdaAdZKVs1qz0WSMmcNmUcDjx9QA5VPXl3LyYKSxlHGylG0ToBZUMxSqFx+91uvlZwzivBHVipkVpUEp+W+99u3rP7oalNmRNn6E9xKnFrrMeWnoSu4q5xLv/NAN3jX+jd47/Q87n/Xu837p/Ew9q2Zd4HzUuc3Jjeg/VyT9/JOss6i19dFO8DuTU1rWSbsN1BRlaFYgQ7MCumZRHFciUwadKXm2l86UQWcCN9/e1wRvLqE6vAN0WNe+Ql37CvWwvLDZrgeDql2zE/vmtHI1ptUJsJRmpR29XkN8XrX2oiKwuKHkiY6gKqq6978cN8bSbt4oMrS8iGoU5AgUymFn8XcYM43KyabatWybc/XsaWsmD8PD9i7ZeQ5Lr2/quvGGfzzxwjHy1lMrV7U/u3rN43iacsPVl6z9yzKzO7oYG/5yHCsP93za88+ez3s6XtzPlf9q58FHNoJaEbQbFOt2PszOoYZrKi8gUTISsYrnqrDIy6QKNlVEaBz9uOHxB2G+oCtUP8DXZ7yH35DBWUPLcjiA3YcPH+Zihw+fe+bwYUSS3QgJMfAhJWQlc2ryYGf/LiMsO9eLGzPKhQyc1/EM11Dke31Es/nl9C0/pBgNZKLJ9HL63jN6ITHrhfh8oSjrnqVTP3LQXROT7uDKsu7F6ojRqg9DL5FSJbui2GpTmFP3z8408h3TbUJ3rxhVZ+odizMElg5SBivzDQuMTcoGbrPypvC6eEA5rZgMQgxHyWRlgSmu/Mv8L8u/rEbezFt4K2eSjQLPQ4hkECXJDLhBNEsYIehGs7HjDFUyZ0MV4ThalkPLOJU3Z8NdRr8gGPwiJybIMs2IDOYvNIIJ2YNNCGOT5jCraJ7ETZ3MH+GP89xmHvMJjDXTZPMB6biZ22zGZnqt2KQjElkrtUhE+oXtvT+nhMEDAD83CITXo3R1IXd1lber+mSV0gW/9cLASAScj/UD3SxnMgOe7Hrl4EHrwYPrhVQONrYubppWF/dPmZnSlZn1nbyNM0h7IFRGye9SHsoK6qL8908Il+EQF+Sygly4SJQ4UvYHUv/R892/evx9/I+HxuX7yoQ9P4zD+3rGkpn4/t3X3XUn3Vc4dD/sK1+AnNqZV7JtNxUerT89WeT5caFo6MpQs/FWo7jQe42wzNhsukW4xSQWOY2cu6jY78wzwr5/KkOWT/30yE9zR43GLIe/uLh/f+TL88PiB/x+OzK44d6e3nvdGZbNDdbLzO6Vo+6waKbhhgjhhlZIjbbooAZbFCmTRQMdqcjESsymIidOL+zTbl9fRG9XiRaGzT7arlmmrZmpoJppW2ZvCYzxJ36IrLsZfpUdrKnpU7WzbB9hSPpE7YdOJpEpREydscnsXK0xMrLB3Xtm1ljVTcOciex6QipOTn3OH7IAgBGtgkCIbmkReyWNmVnIzM7XyuzBjCDYSkI4WJo6QgmHIIYpraAmleL3k/DWt5qvnH/bpktbfrux5xf4gnXDL64bd/OjPR/gJZeHx8wcMf2+jT3bhD2x3fMuf7qsaF/L/LamIdxUu/PKCRct7f/jFsk8fPG4qdcPSZ2FPwq2bSbIjA3l4QGaQw3gMYYUZ+2K34YMrj4c6HtirHMgEHWFVSMOsKMYI1tOo8xO0N2shDGEWQ5vIE/R+aDI6chJSW1WwBDlf2bItzpDvtMZ4v8ZhqQvG/twYcjgMddrw7hcySAaBANv4EWP2+smokkG+ZE5MceZ7cxycmIu5wpihxUSt8EXxE7ZHkQReg5aDJ91uJFyzOV0OcF3JMCvwmBp+swLHMvgo/j752feFFvZPPGGew7f1tOGK+95akjthAeumrit521hT07eJVf0HDn4TE/Ps7NLtw0bUvvF0599W0zfZ3oCdJi+e2tCL2s5ouA3GCQJcTxliGz0m5BBort3tuIol6ZzF6uyaiGy18IbSa9l188nesXc+P8g5kbjf5F388jLmIepHxJXTdBFvnHCmZM/kfEhg2F5coJpeIIvOPcoFzn3J+5WYc+2nuoXeizbYERbYa63wVyN6AUtn811k4R7pwtTfUQlqokQr+n/c36aKfXchj1kSSR7fjI7mQrPf5ndyZQXTT2g/5zZVu6jc38j8e7JdFYjtnVfmfLv90OyDubF4eoOog+c0xEipWfAAVJjSW/o3/fqFdJxIBXMKRXhAOkl/TGldow0je+M0vUi9Ji/Y/gF7Li/o6w8lQ8YnMr79U/locJUnudP5W5v6vFAsUUpV4XNwnaB41TYkTehLSiO+EEQr09Gx9FpJDhUKNyMOCF1FEQX151e9K/0Rf9aX/SzmpLaztmiP8G/F8tQzzEN9e0tsGc3xpavqOru3QzpGRHYw/M7YZm9zL7/Fbrb0XWdnDzFdfGjkJcM2gfm57TuVMm6U2XUEZuOKDpiByTjeEYrt661YRtd8cloGeydvMNnktw+3oStOZLBaiUzJBaWSyyWkBT6hECihhsC9NdZ7ACReSkFFikYzTjgG5M1xjUta5qrKavJ9SvyK+5hy5PKk16zweKRF5GF3CLhGvMyS4vlafMO4055h9nsNN9u/pRw1vxZtqW2tTbOhhPkOS08mK14EwxrM7DgBKy8EdlsJnR+jD4YOnsop9tlm26XNVvUVmA1UKm25ufSZ6aZZCj5dS8ZKjBFAhgDE7BmjbA1wlraImMtvWp4GJNVTYUiykdwnhRIL6T6g720F3yRL0c/r8zRo46clJJqwWhOwREJB6RqcLWstAFJpg1IDtqApB+dSan7dkalIbnlB3vFBBz0SMZzqUjjirppobopM1Nna8NjULviDN1hV+jHJfbKQUrjSfgNGczCkeX6oSB2pcL7cvY40CWFz4chXFVb3jcvHuv5dsUXd2z7MLDds3bmhueevHXR3fg2164jOA/LL2CybvvjuYuvevWd9165GfbMuuQp3g9ymAN75l7NFUC+HPBRG4VG4wzTPG6xsNQ4z2TISSRPMscZwq2T2lSK5fnY6YzjfeGH7LNefohjhGeIr8YxwVvjm+Jo8Ez1zXYs8c72rRJX5ZwlZ90KcmKbxeWa7GxyLnNyTp9ts7JFIYrC5/pkCe0hz9F1YAe4LJa20qVVgJ/3ZYGM0I379P/9UW9H1KVZEskPmcpa9KNfC42oKX8stFFjUXF53IIt3gC1FYXhcprv8kPQGcAB516IfiwpA+Qs69W181t8+gA7K6oUSFpBcTmVhEkSJ+mCkhYBLRKVVKZhbqZtPqZ5KYHxMVFhR0GSx19ekWmnI40RZqhPQtnySOTs8ojuf7G4FSpSkWtV9/KqdJSXdrdAJJav0KVCgRAV2bOlIDv1wUF2NCRyl+8p+Xr3Fz3f4OwP/4St+Nwpuf22ORu7j5Ep5uHRO1Y/i6Ou33TiAOawGffr+bjne0XdvmcBvu/2MQueZr7V6J4p3JcgJ37wxj/XmkwmIbvEVJh9iak2WzTmefJKTOHsklClaVj2xaZx2VGp3rTA9IP87xzrwFBJ0ajQqKJLijaXbCmRhgWH9a8uGWcaF6ztPz04vf9CaU5wTv+mkpaSY0Wngl+Hvimyu5xiToK0dfbzZUnMiigqGsxsSAs6gI5C6JogazRF8Plscm2+zyw7c8oKy+gTxsyniv/MCGv1o76CqFzodh91YcWluZpcLS6+BLZTMqOEeXsuBxU/F/Xw2CNpl0hNJz25Y6VfgtUAJlIqepIHEsYO9hLJc0zUXGCdfsiQ0R/SfZqjrpU2XIjyA7okBXQbE0g7i65ooGC/7YjtuC1p4wO2atsksJ+6WNmUlFgNjNqYWNm8VKxs+XRUNh8dUeoknZZD6omUrAyWT4bIbuJ5yVo+IX0c0p0ZmjUur2IFJ8/SM+qT6dORk9VV6RcUlruoS1hGXcGi1PEHtTiuoWV2dsAYzso+f7B45XZT6ZiVaza4rfja+Aenr/7DXftueHreB1te/vKhp9es3rrthlVb671TCkvnzqyI34mrPnoQ440Ptpxb9N2RVc9zxX84sP/tV19/lcrZBtgcq6i/gST8zw6inwhwOnL+jACQGk/ajTiX4XGcx4UMnNdx8ERMuhujI6KOSID0Ntqdsdd0ZxyGdGcchnTr+zbh00zldETUEQmQjJFaeh2e87iQgfM6rlVEjcMoyycZNxu3GOPGA8bjxtNGCRkDxmXGFuNj6aITxqRRDhhh+5N4whlFbm/yQLqF4ih3E0aiIPKyKBUKiH+M38LH+QP8CV48wJ/mCeJV/ihc8Tw9G6Hyz1Mf00Uln+eppPEyHQKfzUJvak6p+PPU8aRSB8g5TaaSx080jJ/sztziqDtEvaCq6q5I6oyBHUzhxhXL/+txATu1AkdpQ2dnJ//3I0d+zOHDPx6Dvf8WkIsK5ocu6ysVva7kz8jAf/C6l/RnOPsfHMxo9Sf82hUVGFuYx1kxPOV5lg9N5YOHpPL8lGeqFea4ym1CQHhMOC7wkyA5LXABYZnQIiQFHjxTmXCF9H0Y1hJ7TSanbGj5YwgfAF+JIKSCwTuBeKSzh4UAeZQ9iLEHMfYgxh5koLxBOm8ASerRQZpJaCLfl0mUS+Crdqe9VXb1nx/quN7SyRxXjNYjxH0G+4ATH9SyBE7MIluVhPIp93nWae5slsjTQCTfZCm/XsEPKkfdJ9xJN68asq3ZTodPkLDotMgWq9kKxvr86a81w3BbdRdP80WtBW6Nztmt0Tma+lHclE3nbqLvt9ipCTSxVTDlMwpqupmRNmXTlYDr76lvD5hMz/ZN1JNn7ppJKxtWnjRh+Jkmuumqe8uHlcfdp91kmXuLO+4+4ObdHCnLceq22qlbb6dumJ2Mb2c77fZ0mNnLHtdP2MOno7Uf6M4CGGHM4NNcOqA5YDin6WvUOrsnutjRde8ndQZwpkqBwj4VkdS5TJVCXz2sru6yV2LqGIy5XnOKdqNskCWZE5WwXbTmYpvsyMWIhf3rqIUH5tOnyeyVBZczxx6yl6ecSfv6J675qOnxyYrcWbz4wuZn+PAD22uXTShd091Mbr96Sc29b3fvA+EcC75jEciCBXnwxztz2LscWfRVFLYf0Veh5lHMwyockuwxjxcvNETFmGG+uNBgKFdGOEY4h7prlTpHnbPW3SA0GKcqjY5G51T3EmGJca6yxLHEOdd9Hc4xioLlMm66MF2+zHwVN0+YJ19lll0+XrLDDpjdZ+fPzogRsnt3fiWaXZDLdvlcJkxS74tnEjvXSQdFIL2dzFOjCHPTKEJZxhDmvjH3tKCwfLCEkaRIKriAe6HPtOsoDTmei3NZUEkdS8CtughZdcmxpkOKGpBwZLbSYJOdHSIWnyEfExnmMdL34SA1M71mDxKRBl0H6Pk/0kOO8y8jpk7Ld0bREC91LtPvIGbKCbiWjWcjjY19pUd/LXF5I1pO30wwThOmGa8QrjDyENWyV2+z2MNElH60mLnzj33yjtc+wM4b/37n8Z6u3e3rb2/vuG19O8nCRXdf2/NJ9+G/34z92PL2W2//4bW3DqXO6db3LOSDIDcO5MfPaSvNygDlAqVO4avVuEoCan9zKK80pzRvdN4ydbNqGOEakXux6+LcmOEyc4OrIXeRYbF5obLEtTj3gPpO9kfuj7zv+E9mn/SfUJOqM8RHlEjOUH6EMo6/WJmp/M3097wexWS3QsjhE6n98VlNyOrpIzKeDJHx9IqML+opOCpjRdbkJrlF5lUmOKqWfrfkM81ExUd2p69TB0/spRPKOVl/X1amemCjrJNX4qwyUubQ5cFh7X0BI+UHeqKOQoQOYLwZb8FxfBrzAVyNJ4FTTg04M/pYYW9hsOMIzGQWs5MgTC0Ri2cpqZN2jNkxJXawyNYTGF/hxpnhBtufJzAH8MzJ845hKlClD5OYMaG2hL4Lt3wFWp5FbUX6/Sb2BKzIzmUIwvonR9y7YMPRRdccv3HmpoH2p69d9fwzK5vbehYKL7VOmbIx+eBven6885IR3T9yTx4++Naf3jr0Z3oOUp08xbWBLAzmPutw6Qvi1hEPIDUVjDH9MpiU+egx3OcB/3m8IAMPZeD5GXgwA1d7N57VUT4/O3+E8WLj2IJo/rz81ca7jbcWPJ31fMkrnMXo8rpdg+tK3nMJuWQGIUoplt0NhgZjg9xgajA3WBYZFhkXyYtMi8yLLJ3hziJbUbigqKD/sIKZcsw0Nzy338rQyoKWgl/Ij5jv7fdAyX2Dn5SfNf+m6Ml+HeHXws5++uPnfB0J6UiBjjAaytt8HQnpSIGO5CWSH2sOf+VMQ1GhWea9ajiHNw3M89JwKt9TQgUn4Kn2TPLM8mz3HPGINk/As9Rz3MMHPJs8xPMSGKAcUFUWlWvZlFzBGiYKPooJwgomNErvyHaWs2hdsdrLMR7YkHdVHsnz5Ug8HQZzG+nLWGmH8TMti4ol7xtoCnixt8CjZbnLS+ntpVSRPO5USuXbw95N96j0To9K7/Kwh+8eFjrT2hpjSlvJZeff6emISgXF0N4OX+XRYlxMu6bNFOvvwDOENlOcekcJkL060zuixV42lmBRcXlT6YFSUl3aUkpK6RFEAWKDSr+FrKbYAJaAInSEFNlFB6mm7bozqhbYmHLa2ERsKgvW6PafTQdis7JQLRW2pR5savaoLf84wtVoEhhIz5D02QBEbplPX8C2RbpWTGROACtcTk8Izqs0VCL2CnF113L2ni/150C5WQbe9/lXG8E/0IoG+EMQxYftikPJUjgx36LmImM/KRcLAyDxZ8Nl0BrKRfkhi9nQX87F/YqMshjhc1FAyaOeREQBvyOVsMOp4si6detQhoWhvn7j+QJK1PsaU1G4aCDElPRBA3NA9IMsGnS6/CS11YSr22133Lh61dDCX7z+0KSa4cX3TFvz0kx73Ny8cPUip3NQ7q37H4gufH3NkffxBb7FK+aNvSDkLiy9aN3E8df3C0QuvHG+e2rD1IqQLy9LLiirWd0w87FLX2Dn2reA3TlB/1cIvn838tLDIXDUiZrlLLext88d2eWRLFxgyHKacZbTJCLZ7uNMqMzZx3N1ZuwizgzP1VnodlEX08v8VxfzXF0OdpxAPVd23uxiDqKr12d1ZacPFr5L+awuM5UpF/VZLVReki58wIVdE71UTJ3UXfWe9pJl3i3euDfp5enZbGpfMevW05zaVzqi5kIjU1PqZdI/hFCNRyFq5I16UEERzU6HZ2SDMsrszzpo12wrMTJ/1UjYn31M9PQJIdIvWPzUMWUu60nqWlRXVabf2gGx8/KK1WKzEDH1zAqcU96ciywGey6irmlx8TrYb+DO4FDK/nBReCiEHyAUVGiGUZyrXv2ny38zSTF1muxXT5ly98jORzovXDJpaDO5t7vjriHjp0zbtIFUQtDI+OyFeOUU8FkmE/Yhg84uiPasvaEjSn7Zy1CDjgOFszcMRBn7hOH8WT1R+p7DuwQDkg0iFmUkGA0CJkIBVXdhUOSjw8pHh+1lZbCvVtN1yN01VMAo314pUzttsVcaITwqN9CEgHHqgBync6D4i2b0B8tRP0iYN2GE4BI5IYGrY9pN/QaWIxUSm7k/6mcMy5VoqHwhGi9HcZTEDPXGK/GVZKFhoXEVug5fR643rDJeJ6/H68nt3B3SBkOr8dfoQeM98gvoCfkltEtqk99Er8nH0J/kr9Cn8o/ojFwC05HdyCn3Q2G5Qp6ENNkoaA5nuQCCWq7/ZQTMh04dUcdHs7H3bhGzcHQtaBlzROiqsFIiCGYTfcvtowisDcDhyOEIGlRdzeQkV6uQJYOh0ChnG40y4giBYCsbYxiIjGSjwUAIFiXZyCEsDDJjc75B0zRji5EYEzh3hwbRNREA04wq0XC+6cs/UoHt8nq6G7sbve6uk43p12QgZqLWq7rKXknfili/hr0UAVkM3B56rtrn3Qb6rp2OB3FZltM1rCKrDOMXe656+WRhwB35anfP1Xy4+9b5S6dfSzb8eExEqf8bAvtoDd+MZgAcB6gCiAJ402UTAGZTHGh3C9FktxBF9wtvoEchf4L/FG2F8v08QpOBpg5gNH4DbQC4BfD1AGNZjlA15LdA7tXG1V8anTG9RqsedUHVyBGVwyuGlpeVDhk8aOCAkkhx/35F4cKCUH5QDfjzfLlejxuCv+wsh12xWS1mEyyvJAo8RzAqqQ2Na1Lj4aY4Hw5deOEAeh2aDQWzMwqa4ioUjetLE1ebGJnal1IDyiv/g1JLUWq9lFhRq1DVgBK1NqTGD48NqQk8c0o94HeNDcXUeBfDJzB8M8MtgAeDcINa614wVo3jJrU2Pu7aBa21TWOhuTaTPCY0Zp48oAS1ySZATYDFXaFlbdg1CjOEuGpHtBFksMCg4t7Q2Nq4JzSWjiDOFdbOnhufPKW+dmxuMBgbUBLHY+aErogj+seaEUaCxrBu4uKYuMS6URfS2aA71baSA60bEwq6oilinhuaO7uhPs7NjtE+7BHod2zcdcNJ9/lLaNwxpn59Zm0u11rrXqjSy9bW9Wp8y5T6zNogTWMxaAPuJYXjmlrHQdcbYRHr6N/xxsltsfo4vg26VOlM6KxS80v9tWth0yI1bgyNDi1oXdQErPG2xtHU64PtXq+2O3kCeWvV1un1oWC8OjcUmz3W15aNWqde3+HRVE/fmgElbYo9tbBtVlsaMVsykXm9dQxj5BSrm9q7spiOKHQRCERcnaPCSOpDMKfhNJk3HLXOGQ5k8IlhuCs+FziyMG4c09SqjKDl9P64UKiE1NZ/I5CAUNdXfUtmp0vEQuXfiKJUTnpFDep1PB6JxIuLqYhIY4CnMMZR7HrogJJrEyQUWqaokMHyocmwtrNjIwbB8geDlMF3JjR0BVzEW6bUp65VdEVuO9IGRWJx0kRrDug1OTNoTYte03t7UwgkuZP9x7OcuCHc+7MpzqzaBSPi2Pl/qZ6Xqk8/W1RrW5vSa1s3vc9Vqn54b10ai2eNqedySRojuRyrTf2Rrk4CF/XmOF8IP5EJ9dyEZACpZCVYHRdXmi5MpTE5GPwfbwKXi97FsvO3pYcZHxHpez2yz3Wf4ZlbORgwHyZ102e2tsp96kDUUh1elM5A4tH0+qA6Jo5mgGYWwg/cpOEUYrlxDZZsDCUA+UsVpS/7EOam8Rh8qHQOKBkHhq61dVxIHdfa1Do7kWy5IqQqodbd5BXySuuy2iZdcBLJPXfmxsdtjMFaLcAjQCkIGt0WwhumtGl4w7SZ9bsVhNQN0+vbCSZjmkbH2gqgrn63ipDGSgktpYX0QqUXqA7DJNuJgdHn7tYQamG1PCtg13MSGLEyg16G0ZwESZUpqY7CrCP6tw1zEnyqRtOpeSgzpMpaUtT90tQGqFFozR72t9SsMvWhxgmchEyxY7pMKy6N1JtJa900YBqtlIfnyhnVKr0xjkPxWaFVwTZoMx4NXR+EwlBcBQMHRG1ovC/W2qrCNwTdz4nWp1JahUt80FKM/guANG2uLxbKuDTDrYwVHT6qdr293aj3tgJ6o0ir3l18zs/2BqOP48toyn5s+G3DUCjVP2xsqU5bG1pnhoJgN/Nox+lxwKXVF2MtwEgepCMB7f4/Ko5rlQplbmRzdHJlYW0KZW5kb2JqCjcyIDAgb2JqCjw8L0ZpbHRlci9GbGF0ZURlY29kZS9MZW5ndGggMjE0Pj5zdHJlYW0KeJztzjcOQlEMBMAl50/OcP9rYr2OAgpoZ6S15FA4/+p93PRbHWSYUcaZZJpZ5jVZZPl2t0pXdZ1Ntq3f/fDFvnKoHCunNjlXLrnm1rp75ZFnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgC9e/EsBtAplbmRzdHJlYW0KZW5kb2JqCjY5IDAgb2JqCjw8L0ZpbHRlci9GbGF0ZURlY29kZS9MZW5ndGggMTY0OD4+c3RyZWFtCnicbdjNaiW5AQXgfT/FXc4shm6ppJIETUOYEOhFfkgnDyCppMGQdhu3Z9FvH9vfZJIZcsE2da7LHL5zMYXe/vjxjx/v755ub//2+GV+Wk+3fXd/Pa6vX35+nOs21k93929CvF138+mXq9fv83N/ePNy86dvX5/W54/3+8ub9+9vb//+/ObXp8dvt+/+cH0Z6/s3b//6eK3Hu/ufbt/988dP39/efvr54eFf6/O6f7q9u334cLvWfv5Df+4Pf+mf1+3t620/fLye3797+vbD8z3//Y1/fHtYt/h6HZSZX6719aHP9djvf1pv3r97fn24vf/T8+vDm3V//e798O6d+8b+7Q3v3u39+uP56jkMwiAMwiiMwig8hIfwECZhEiZhFmZhFp7CU3gKi7AIi7AKq7AKm7AJm7ALu7ALh3AIh3AKp3AKL+ElvIRLuIRLuIVbuF/DwDPwDDwDz8Az8Aw8A8/AM/AMPAPPwDPwDDwDz8Az8Aw8A8/AM/AMPAPPwDPwDDwDz8Az8Aw8A8/AM/AMPAPPwDPwDDwDz8Az8Aw8A8/AM/AMPAPPyDPyjDwjz8gz8ow8I8/IM/KMPCPPyDPyjDwjz8gz8ow8I8/IM/KMPCPPyDPyjDwjz8gz8ow8I8/IM/KMPCPPyDPyjDwjz8gz8ow8I8/IM/KMPCPPg+fB8+B58Dx4HjwPngfPg+fB8+B58Dx4HjwPngfPg+fB8+B58Dx4HjwPngfPg+fB8+B58Dx4HjwPngfPg+fB8+B58Dx4HjwPngfPg+fB8+B58Dx4HjwPngfPxDPxTDwTz8Qz8Uw8E8/EM/FMPBPPxDPxTDwTz8Qz8Uw8E8/EM/FMPBPPxDPxTDwTz8Qz8Uw8E8/EM/FMPBPPxDPxTDwTz8Qz8Uw8E8/EM/FMPBPPzDPzzDwzz8wz88w8M8/MM/PMPDPPzDPzzDwzz8wz88w8M8/MM/PMPDPPzDPzzDwzz8wz88w8M8/MM/PMPDPPzDPzzDwzz8wz88w8M8/MM/PMPDPPk+fJ8+R58jx5njxPnifPk+fJ8+T5evXyWPGfx4f/80Bxwj5hn7BP2CfsE/YJ+4R9wj5hn7BP2CfsE/YJ+4R9wj5hn7BP2CfsE/YJ+4R9wj5hn7BP2CfsE/YJ+4R9wj5hn7BP2AV2gV1gF9gFdoFdYBfYBXaBXWAXH97Cs/AsPAvPwrPwLDwLz8Kz8Cw8C8/Cs/AsPAvPwrPwLDwLz8Kz8Cw8C8/Cs/AsPAvPwrPwLDwLz8Kz8Cw8C8/Ks/KsPCvPyrPyrDwrz8qz8qw8K8/Ks/KsPCvPyrPyrDwrz8qz8qw8K8/Ks/KsPCvPyrPyrDwrz8qz8qw8K8/Ks/KsPCvPyrPyrDwrz8qz8qw8K8/Gs/FsPBvPxrPxbDwbz8az8Ww8G8/Gs/FsPBvPxrPxbDwbz8az8Ww8G8/Gs/FsPBvPxrPxbDwbz8az8Ww8G8/Gs/FsPBvPxrPxbDwbz8az8Ww8G8/Os/PsPDvPzrPz7Dw7z86z8+w8O8/Os/PsPDvPzrPz7Dw7z86z8+w8O8/Os/PsPDvPzrPz7Dw7z86z8+w8O8/Os/PsPDvPzrPz7Dw7z86z8+w8O8/Bc/AcPAfPwXPwHDwHz8Fz8Bw8B8/Bc/AcPAfPwXPwHDwHz8Fz8Bw8B8/Bc/AcPAfPwXPwHDwHz8Fz8Bw8B8/Bc/AcPAfPwXPwHDwHz8Fz8Bw8B8/Jc/KcPCfPyXPynDwnz8lz8pw8J8/Jc/KcPCfPyXPynDwnz8lz8pw8X69+80CR6u+eJybryXqynqwn68l6sp6sJ+vJerKerCfryXqynqwn68l6sp6sJ+vJerKerC/WF+uL9cX6Yn2xvlhfrC/WF+uL9cX6Yn2xvlhfrC/WF+uL9cX6Yn2xvlhfPrtLz6Xn0nPpufRcei49l55Lz6Xn0nPpufRcei49l55Lz6Xn0nPpufRcei491y897b7svuy+7L7svuy+7L7svuy+7L7svuy+7L7svuy+7L7svuy+7L7svuy+7L7svuy+eW6em+fmuXlunpvn5rl5bp6b5+a5eW6em+fmuXlunpvn5rl5bp6b5+a5eW6em+fmuXlunpvn5rl5bp6b5+a5eW6em+fmuXlunpvn5rl5bp6b5+vV//4veDm+fDll/fVsdP78+Ljun16PYl/PQ19OQu/u16+ntQ9fHl7uevn6N8FLPl4KZW5kc3RyZWFtCmVuZG9iago1IDAgb2JqCjw8L1R5cGUvT2JqU3RtL04gNTkvRmlyc3QgNDU4L0ZpbHRlci9GbGF0ZURlY29kZS9MZW5ndGggMTc3Mz4+c3RyZWFtCnicvVhbb9s2FH7Pr+BbGwwx76Q0FAUcu0nTXBF7SzdDD4qtJSocK7CVodmv33dExZZcx6kxYGkqieTHc+fhOTFMMM+kdEwxZWImBdOxxQQz0jCpmPGaSc1s5BhAXmAywrzwTAkmrTZMSSa9wT4mYyuZwu4YaIVfYT3TAgiBZSxJb5mKmFIiYkYzpbVjBox1pMEPAgAMSsp47ItBShmmgbdeMg2ODrw1kXaWaZDyEJAk8BHwoBfhoUEv8jEz2BdDCIN9MegZB1HA3GCroHWQluBnSTQoCeW1gooWLJSNGX61FhiDhbawAETQsWMOeAPhHMYmssyCjoVygGjrDXPAO+mZw9jhYcHXC9ADXw9iDngPE5MKEZQmE0WQ3zmyPJQzMIGAEhBRwDgOogvILy1MJcGXTAd+XtA7ZjCN8XDbhw98+PyY8av0LuPX2aJ4mo+zBZwr2DU/zyZ5elh8HwkMHazmY5XwXjErs1m5GDkCsbh6RvRM+KCcP43Lq3ROACb4ML1d8AEPE/A1QB8/gufVvBgPsnLEr/pHjA+z7yXjJw+Q4bB+9+r3ScI/fS+PB2VaZth3rCnWSLZjR+FW0eNHkAiLR1Xo0eKRpegLi18vb79lY1r/itAzYbYSYpiX04y9747HxROku87u8kU5T8u8mLGjYv7ADli/GD/1in2Sd/I0zubsPc0s8rsZ65//LcU+782zakcfAmL1VyWUlQIxZ62y9kD4d0K82+fnxWQ7opJonDLJD8/5Bbin02qq18VUNX/Wg0HPvtDjhsmOph9+fgaD8EGXwfDZ2tbKsWQbPni6LWlAM4Ifpousmu5WP79053k6PR/yT7NxMclnd/xkAm/l5fPBZ97PFuNsNklnJe1YjKQLjh4Wv81ywDOc4qVX32R42GB4cFhMJz/LNfqBa7yBKz1o6zx/LIs5pRoKhtfUfZGxd9KnZSKjaDAsjk/65+njUiCaHDwvyuzhZPZXAY51pDwjdibFbbbPL+eTbA4d2PuXPfsg//g4zR4o7gXC8AaHaOStSCjjIbl434m0EnTcKUk55zpxTCcVmQvnc88r1ZHOx55S3MhJAXgcVYl3ubIkklAeGq0WRINeY0NCacc1F5E+HJhZ6zrSKiRF5AWvWGOs2Wgl62p+9aVW1JEfR8shQ1rtCOEjmbBIYtRkgww40o11v5FLwmLRUCtJeP8GmVe84XbZdvumoPu/fd+0YlK5PG74Ecm5bXTXNIdoGrsxu4qJZnTQv4ahl0ZegYIZEYptM64sWA0v0ods/cQcTdO7BTO8S6ezhHNsR3ltTH1eS3agpOzE0giHmyB7+B3XZicCS8N76ePnLL+7LxFhmIMGkp+U6TQfd2d3yMKiYnpIl82Bc6ZjLYRmB1qZjhce+iqBagAVATbbWEdJhT/KpxnuPPVjLtikzaZA2F0lD9N6GUW7qaR8J1YxztqBBgHjDJxVqyR9x8JBuqWSbqtE1/MCNy/dU5Kf5pPFqLrJkhUkXL3DeZZdF0XJT6lkonMQ7l6av8A1e5o9g8BqjgqGFqfLp3Kaz8DsKJ8vSqrDiMhZuvz+uatznwxYUvm2koGKOxoNPlG5VZEKWjD+9Y8/YcVO7GSMBCRNRymNKkgkbe0+4VChnKA7mA4Xv6K6kUiejgJFqueqV6CrbXiFSkX78IrCKxQuRoRXJSjbM4GM0RutW/O/Isa1de+YCRLgStoNHu0G97vB3W5wuxvc7AbXu8HVK3BUk9NsteV0ZIKbTXCzCW42wc0m2t2Fajc5X0F/lhvh4jWtgKojlVQKYWnFNunbW2yIXat22BKOiTU7bAlGtu6nt1CT0sotbWgfUBO9QKOfh8ZboOSpYLuWp+QWeLB4Cy62CuJrmBNvyryEyrdkVutCbMsmVq6jo61iuBcx1JsSL6H6LYnNugzbMlQIuCbabRXjJYSceVPiJdS+JbFbl2Fb1gvx3kS/lvSGn0mMpV6BS3cE7GWdsnrFdPCYzii/bEtI4bw0WYbEed+5/6dIp4tv4zw3tnVnoienNqdBdXW384unhwXaDufrI7v5kgwC1+arDV67vw6YOnzrgEd5WeeoaMfbtX25bmkY1/o/KpBbJf2w1z3+crOsS1dtoQtneUNPCe29eJ1vqxFYayi83Mr9v3YIMnQIqqr5E4pnao0SSnhIuo5t+Z9QyFSgaitcOHLU0jms7MFo1Duxakai8ax7OXRV6NPQRiVUfFbb6UvXX3tS2KqNo8no5UuKljA0Y1+IyFoGGiXNLorCc1tl/mO1fBMKaiPCECckK8f39R812i1C1Ry81NA6Thr1OI0bFX2rludfa5CV0ao1WHNpVYinD/mUnEhz+3XxL+qGQatGse7rVPkvKqWjuQplbmRzdHJlYW0KZW5kb2JqCjc0IDAgb2JqCjw8L1Jvb3QgMSAwIFIvSW5mbyAyIDAgUi9JRFsoYjY4OGY1MDEtZjgxOS00MjllLWE2YjItOWNjYjI0MGQ1ZTY2KSAoYjY4OGY1MDEtZjgxOS00MjllLWE2YjItOWNjYjI0MGQ1ZTY2KV0vVHlwZS9YUmVmL0luZGV4WzAgNzVdL1dbMSA0IDRdL1NpemUgNzUvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAyMjE+PnN0cmVhbQp4nE3RS04CQRSF4WqgRW36ISqIQCPaPFR8tfLShC041RkzhqyBDeACWIqrgBkJA3cit5L6k6qkU1/fc5JKqpRe/7IcpZYf+icjn6t34AElna1voD7tsqMnIdHCjrIgB1xwIGVvZpeHIC+Rn9rRoUyCX3tyBI4lihJz+nRud95AAfjS+YntTgT6IAAhqIEquAQVcAHKoATOwRk4BUVwAprgCjRADOrgBlyDDmiDe3AHnsAjSEECWqALbkEPPIBn8AJewQCM5OY3X/bNj8G7ROuJecHVzuDvW2MPIhcW+QplbmRzdHJlYW0KZW5kb2JqCnN0YXJ0eHJlZgo1NzQzMwolJUVPRgo=","display":"inline","includeInDownload":"true","signerMustAcknowledge":"no_interaction","templateLocked":"false","templateRequired":"false"}],"emailSubject":"Complete with Docusign: Account Registration Form - DocuCo.pdf","emailBlurb":"Please complete this account registration form.","signingLocation":"Online","authoritativeCopy":"false","notification":{"reminders":{"reminderEnabled":"false","reminderDelay":"0","reminderFrequency":"0"},"expirations":{"expireEnabled":"true","expireAfter":"120","expireWarn":"0"}},"enforceSignerVisibility":"false","enableWetSign":"true","allowMarkup":"false","allowReassign":"true","customFields":{"textCustomFields":[{"fieldId":"11258135749","name":"envelopeTypes","show":"false","required":"true","value":"BankAccountOpeningAgreements"},{"fieldId":"11258135750","name":"templateUsageRestriction","show":"false","required":"false","value":"allOptions"}],"listCustomFields":[]},"recipients":{"signers":[{"defaultRecipient":"false","tabs":{"signHereTabs":[{"stampType":"signature","name":"SignHere","tabLabel":"signature","scaleValue":"1","optional":"false","documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"72","yPosition":"386","tabId":"0e52d949-a9cd-4dfa-83f6-d1415b31d77c","templateLocked":"false","templateRequired":"false","tabType":"signhere","agreementAttributeLocked":"false"}],"dateSignedTabs":[{"name":"DateSigned","value":"","tabLabel":"dateSigned","font":"arial","bold":"false","italic":"false","underline":"false","fontColor":"black","fontSize":"size9","localePolicy":{},"documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"337","yPosition":"403","width":"0","height":"0","tabId":"49ed1de8-7c9a-4d9a-915f-61a1e51d529a","templateLocked":"false","templateRequired":"false","tabType":"datesigned","agreementAttributeLocked":"false"}],"textTabs":[{"validationPattern":"","validationMessage":"","requireInitialOnSharedChange":"false","requireAll":"false","name":"Account Holder Name","value":"","originalValue":"","required":"true","locked":"false","concealValueOnDocument":"false","disableAutoSize":"false","maxLength":"4000","tabLabel":"accountHolderName","font":"arial","bold":"false","italic":"false","underline":"false","fontColor":"black","fontSize":"size9","localePolicy":{},"documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"210","yPosition":"170","width":"366","height":"19","tabId":"b2f7392e-f130-42ca-90a0-b7f84b31cf44","templateLocked":"false","templateRequired":"false","mergeFieldXml":"{\"admBindings\":[{\"fqn\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0.BankAccountOpening\",\"path\":\"$.accountHolderName\",\"position\":\"0\"}]}{\"folder\":\"BankAccountOpening\",\"folderProperty\":\"Account Holder Name\",\"initialValue\":\"accountHolderName\",\"name\":\"Account Holder Name\",\"legacyPath\":\"$.BankAccountOpening[0].accountHolderName\",\"required\":true,\"type\":\"martiniDataTabs\",\"collectionItems\":{\"0\":\"BankAccountOpening 1\"},\"modelType\":\"data-verification\",\"namespace\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0\"}{}{}","tabType":"text","tooltip":"Account Holder Name","extensionData":{"extensionGroupId":"a9084b3e-4147-45fb-b985-c354dded21a3","publisherName":"John Doe","applicationId":"a0833a82-3682-4555-bd64-61172372adfe","applicationName":"Bank Account Opening","actionName":"","actionContract":"","extensionName":"","requiredForExtension":true,"actionInputKey":"accountHolderName","extensionPolicy":"MustVerifyToSign","connectedFieldsData":{"typeSystemNamespace":"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0","typeName":"BankAccountOpening","supportedOperation":"verify","supportedUri":"/connected-data/v1/connected-objects/com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0/BankAccountOpening/verify","propertyName":"accountHolderName"}},"agreementAttributeLocked":"false"},{"validationPattern":"^[0-9a-zA-Z]+$","validationMessage":"Invalid validation for accountNumber","shared":"false","requireInitialOnSharedChange":"false","requireAll":"false","name":"Account Number","value":"","originalValue":"","required":"true","locked":"false","concealValueOnDocument":"false","disableAutoSize":"false","maxLength":"4000","tabLabel":"accountNumber","font":"arial","bold":"false","italic":"false","underline":"false","fontColor":"black","fontSize":"size9","localePolicy":{},"documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"210","yPosition":"243","width":"366","height":"19","tabId":"1f3e583e-3548-4622-a454-7354854d9b7f","templateLocked":"false","templateRequired":"false","mergeFieldXml":"{\"admBindings\":[{\"fqn\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0.BankAccountOpening\",\"path\":\"$.accountNumber\",\"position\":\"0\"}]}{\"folder\":\"BankAccountOpening\",\"folderProperty\":\"Account Number\",\"initialValue\":\"accountNumber\",\"name\":\"Account Number\",\"legacyPath\":\"$.BankAccountOpening[0].accountNumber\",\"required\":true,\"type\":\"martiniDataTabs\",\"collectionItems\":{\"0\":\"BankAccountOpening 1\"},\"modelType\":\"data-verification\",\"namespace\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0\"}{}{}","tabType":"text","tooltip":"Account Number","extensionData":{"extensionGroupId":"a9084b3e-4147-45fb-b985-c354dded21a3","publisherName":"John Doe","applicationId":"a0833a82-3682-4555-bd64-61172372adfe","applicationName":"Bank Account Opening","actionName":"","actionContract":"","extensionName":"","requiredForExtension":true,"actionInputKey":"accountNumber","extensionPolicy":"MustVerifyToSign","connectedFieldsData":{"typeSystemNamespace":"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0","typeName":"BankAccountOpening","supportedOperation":"verify","supportedUri":"/connected-data/v1/connected-objects/com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0/BankAccountOpening/verify","propertyName":"accountNumber"}},"agreementAttributeLocked":"false"},{"validationPattern":"","validationMessage":"","shared":"false","requireInitialOnSharedChange":"false","requireAll":"false","name":"Bank Name","value":"","originalValue":"","required":"true","locked":"false","concealValueOnDocument":"false","disableAutoSize":"false","maxLength":"4000","tabLabel":"bankName","font":"arial","bold":"false","italic":"false","underline":"false","fontColor":"black","fontSize":"size9","localePolicy":{},"documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"210","yPosition":"207","width":"366","height":"19","tabId":"b7422ba2-f941-48ec-bc5f-0dc006d51745","templateLocked":"false","templateRequired":"false","mergeFieldXml":"{\"admBindings\":[{\"fqn\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0.BankAccountOpening\",\"path\":\"$.bankName\",\"position\":\"0\"}]}{\"folder\":\"BankAccountOpening\",\"folderProperty\":\"Bank Name\",\"initialValue\":\"bankName\",\"name\":\"Bank Name\",\"legacyPath\":\"$.BankAccountOpening[0].bankName\",\"required\":true,\"type\":\"martiniDataTabs\",\"collectionItems\":{\"0\":\"BankAccountOpening 1\"},\"modelType\":\"data-verification\",\"namespace\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0\"}{}{}","tabType":"text","tooltip":"Bank Name","extensionData":{"extensionGroupId":"a9084b3e-4147-45fb-b985-c354dded21a3","publisherName":"John Doe","applicationId":"a0833a82-3682-4555-bd64-61172372adfe","applicationName":"Bank Account Opening","actionName":"","actionContract":"","extensionName":"","requiredForExtension":true,"actionInputKey":"bankName","extensionPolicy":"MustVerifyToSign","connectedFieldsData":{"typeSystemNamespace":"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0","typeName":"BankAccountOpening","supportedOperation":"verify","supportedUri":"/connected-data/v1/connected-objects/com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0/BankAccountOpening/verify","propertyName":"bankName"}},"agreementAttributeLocked":"false"},{"validationPattern":"^\\d{9}$","validationMessage":"Invalid validation for routingNumber","shared":"false","requireInitialOnSharedChange":"false","requireAll":"false","name":"Routing Number","value":"","originalValue":"","required":"true","locked":"false","concealValueOnDocument":"false","disableAutoSize":"false","maxLength":"4000","tabLabel":"routingNumber","font":"arial","bold":"false","italic":"false","underline":"false","fontColor":"black","fontSize":"size9","localePolicy":{},"documentId":"1","recipientId":"79452210","pageNumber":"1","xPosition":"210","yPosition":"281","width":"364","height":"19","tabId":"fda0e852-0068-4156-9e99-305f353bf084","templateLocked":"false","templateRequired":"false","mergeFieldXml":"{\"admBindings\":[{\"fqn\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0.BankAccountOpening\",\"path\":\"$.routingNumber\",\"position\":\"0\"}]}{\"folder\":\"BankAccountOpening\",\"folderProperty\":\"Routing Number\",\"initialValue\":\"routingNumber\",\"name\":\"Routing Number\",\"legacyPath\":\"$.BankAccountOpening[0].routingNumber\",\"required\":true,\"type\":\"martiniDataTabs\",\"collectionItems\":{\"0\":\"BankAccountOpening 1\"},\"modelType\":\"data-verification\",\"namespace\":\"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0\"}{}{}","tabType":"text","tooltip":"Routing Number","extensionData":{"extensionGroupId":"a9084b3e-4147-45fb-b985-c354dded21a3","publisherName":"John Doe","applicationId":"a0833a82-3682-4555-bd64-61172372adfe","applicationName":"Bank Account Opening","actionName":"","actionContract":"","extensionName":"","requiredForExtension":true,"actionInputKey":"routingNumber","extensionPolicy":"MustVerifyToSign","connectedFieldsData":{"typeSystemNamespace":"com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0","typeName":"BankAccountOpening","supportedOperation":"verify","supportedUri":"/connected-data/v1/connected-objects/com.docusign.connecteddata._WyJiMGY1ZWJiNS0wN2E3LTRhZWQtODM2Zi03MDA5NzkzYzQ0NWQiLDAsImEwODMzYTgyLTM2ODItNDU1NS1iZDY0LTYxMTcyMzcyYWRmZSIsImQ4OGMyNTZiLTUyZGQtNGUyMC04OGYzLWMyMjdjZGFhN2E1MCIsMF0@2.0.0/BankAccountOpening/verify","propertyName":"routingNumber"}},"agreementAttributeLocked":"false"}]},"signInEachLocation":"false","agentCanEditEmail":"false","agentCanEditName":"false","requireUploadSignature":"false","name":"","email":"","recipientId":"79452210","recipientIdGuid":"00000000-0000-0000-0000-000000000000","accessCode":"","requireIdLookup":"false","routingOrder":"1","note":"","roleName":"Account Holder","completedCount":"0","deliveryMethod":"email","templateLocked":"false","templateRequired":"false","inheritEmailNotificationConfiguration":"false","recipientType":"signer"}],"agents":[],"editors":[],"intermediaries":[],"carbonCopies":[],"certifiedDeliveries":[],"inPersonSigners":[],"seals":[],"witnesses":[],"notaries":[],"recipientCount":"1"},"envelopeIdStamping":"true","autoNavigation":"true","uSigState":"esign","allowComments":"true","disableResponsiveDocument":"true","anySigner":null,"envelopeLocation":"current_site"} --------------------------------------------------------------------------------