diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 90ea33ab..e074c76b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.130.0" + ".": "0.131.0" } diff --git a/.stats.yml b/.stats.yml index c89f8408..4f6a4f90 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 185 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-a45946df228eec554b3cd2491f658bd5a45cb91509da0a9f92d50468ea88072f.yml -openapi_spec_hash: 24c7c13e1e7385cab5442ca66091ffc6 -config_hash: 50031f78031362c2e4900222b9ce7ada +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-ee8607f0a2cdcaee420935050334a439db8dd097be83023fccdaf1d6f9a7de14.yml +openapi_spec_hash: 0f21c68cdddb7c5bd99f42356d507393 +config_hash: fb5070d41fcabdedbc084b83964b592a diff --git a/CHANGELOG.md b/CHANGELOG.md index 29d68c04..af5897e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 0.131.0 (2026-03-04) + +Full Changelog: [v0.130.0...v0.131.0](https://github.com/lithic-com/lithic-node/compare/v0.130.0...v0.131.0) + +### Features + +* **api:** add action_counts to rule performance reports and code to authorization actions ([b721196](https://github.com/lithic-com/lithic-node/commit/b7211961ba92cc5cd68ad633592b5428060e8478)) +* **api:** Add Hold API for financial account fund reservations ([582aeb7](https://github.com/lithic-com/lithic-node/commit/582aeb7164a9e9523becb601a08e7393904cd4e5)) +* **api:** Remove deprecated beneficial owner entities field ([e0b8292](https://github.com/lithic-com/lithic-node/commit/e0b8292748ddb37a3758a909c5e7314c511985e4)) + + +### Chores + +* **internal:** codegen related update ([bccb03c](https://github.com/lithic-com/lithic-node/commit/bccb03cc6e6d046aa76dac2b77237233d1a614a7)) + ## 0.130.0 (2026-02-27) Full Changelog: [v0.129.0...v0.130.0](https://github.com/lithic-com/lithic-node/compare/v0.129.0...v0.130.0) diff --git a/api.md b/api.md index a417649d..405a5437 100644 --- a/api.md +++ b/api.md @@ -84,6 +84,7 @@ Types: - AuthRule - AuthRuleCondition +- BacktestStats - Conditional3DSActionParameters - ConditionalACHActionParameters - ConditionalAttribute @@ -94,7 +95,7 @@ Types: - ConditionalValue - EventStream - MerchantLockParameters -- RuleStats +- ReportStats - VelocityLimitParams - VelocityLimitPeriod - V2ListResultsResponse diff --git a/examples/transactions.ts b/examples/transactions.ts index daded2f8..a93041a2 100755 --- a/examples/transactions.ts +++ b/examples/transactions.ts @@ -22,7 +22,7 @@ async function simulateAuthDeclined(card: Lithic.Cards.Card) { const authResponse = await client.transactions.simulateAuthorization({ pan: card.pan!, - amount: 999999999999, + amount: 2000000000, descriptor: 'coffee shop', }); diff --git a/package.json b/package.json index a3cc6c7d..07f2a8e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lithic", - "version": "0.130.0", + "version": "0.131.0", "description": "The official TypeScript library for the Lithic API", "author": "Lithic ", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index bf005118..334377e5 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -1,7 +1,7 @@ { "dxt_version": "0.2", "name": "lithic-mcp", - "version": "0.130.0", + "version": "0.131.0", "description": "The official MCP Server for the Lithic API", "author": { "name": "Lithic", diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 2a29d262..5d4a8b47 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "lithic-mcp", - "version": "0.130.0", + "version": "0.131.0", "description": "The official MCP Server for the Lithic API", "author": "Lithic ", "types": "dist/index.d.ts", @@ -39,8 +39,9 @@ "express": "^5.1.0", "fuse.js": "^7.1.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz", - "morgan": "^1.10.0", - "morgan-body": "^2.6.9", + "pino": "^10.3.1", + "pino-http": "^11.0.0", + "pino-pretty": "^13.1.3", "qs": "^6.14.1", "typescript": "5.8.3", "yargs": "^17.7.2", @@ -57,7 +58,6 @@ "@types/cors": "^2.8.19", "@types/express": "^5.0.3", "@types/jest": "^29.4.0", - "@types/morgan": "^1.9.10", "@types/qs": "^6.14.0", "@types/yargs": "^17.0.8", "@typescript-eslint/eslint-plugin": "8.31.1", diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 2939b217..0d52a8a7 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -17,6 +17,7 @@ import { import { Tool } from '@modelcontextprotocol/sdk/types.js'; import { readEnv, requireValue } from './util'; import { WorkerInput, WorkerOutput } from './code-tool-types'; +import { getLogger } from './logger'; import { SdkMethod } from './methods'; import { McpCodeExecutionMode } from './options'; import { ClientOptions } from 'lithic'; @@ -83,6 +84,8 @@ export function codeTool({ }, }; + const logger = getLogger(); + const handler = async ({ reqContext, args, @@ -107,11 +110,27 @@ export function codeTool({ } } + let result: ToolCallResult; + const startTime = Date.now(); + if (codeExecutionMode === 'local') { - return await localDenoHandler({ reqContext, args }); + logger.debug('Executing code in local Deno environment'); + result = await localDenoHandler({ reqContext, args }); } else { - return await remoteStainlessHandler({ reqContext, args }); + logger.debug('Executing code in remote Stainless environment'); + result = await remoteStainlessHandler({ reqContext, args }); } + + logger.info( + { + codeExecutionMode, + durationMs: Date.now() - startTime, + isError: result.isError, + contentRows: result.content?.length ?? 0, + }, + 'Got code tool execution result', + ); + return result; }; return { metadata, tool, handler }; @@ -157,6 +176,11 @@ const remoteStainlessHandler = async ({ }); if (!res.ok) { + if (res.status === 404 && !reqContext.stainlessApiKey) { + throw new Error( + 'Could not access code tool for this project. You may need to provide a Stainless API key via the STAINLESS_API_KEY environment variable, the --stainless-api-key flag, or the x-stainless-api-key HTTP header.', + ); + } throw new Error( `${res.status}: ${ res.statusText diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index 8dd26a03..0fa5587f 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -1,7 +1,8 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Metadata, McpRequestContext, asTextContentResult } from './types'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; +import { Metadata, McpRequestContext, asTextContentResult } from './types'; +import { getLogger } from './logger'; export const metadata: Metadata = { resource: 'all', @@ -50,19 +51,49 @@ export const handler = async ({ }) => { const body = args as any; const query = new URLSearchParams(body).toString(); + + const startTime = Date.now(); const result = await fetch(`${docsSearchURL}?${query}`, { headers: { ...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }), }, }); + const logger = getLogger(); + if (!result.ok) { + const errorText = await result.text(); + logger.warn( + { + durationMs: Date.now() - startTime, + query: body.query, + status: result.status, + statusText: result.statusText, + errorText, + }, + 'Got error response from docs search tool', + ); + + if (result.status === 404 && !reqContext.stainlessApiKey) { + throw new Error( + 'Could not find docs for this project. You may need to provide a Stainless API key via the STAINLESS_API_KEY environment variable, the --stainless-api-key flag, or the x-stainless-api-key HTTP header.', + ); + } + throw new Error( - `${result.status}: ${result.statusText} when using doc search tool. Details: ${await result.text()}`, + `${result.status}: ${result.statusText} when using doc search tool. Details: ${errorText}`, ); } - return asTextContentResult(await result.json()); + const resultBody = await result.json(); + logger.info( + { + durationMs: Date.now() - startTime, + query: body.query, + }, + 'Got docs search result', + ); + return asTextContentResult(resultBody); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index b1f56bed..cbca4fd1 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -4,9 +4,10 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { ClientOptions } from 'lithic'; import express from 'express'; -import morgan from 'morgan'; -import morganBody from 'morgan-body'; +import pino from 'pino'; +import pinoHttp from 'pino-http'; import { getStainlessApiKey, parseClientAuthHeaders } from './auth'; +import { getLogger } from './logger'; import { McpOptions } from './options'; import { initMcpServer, newMcpServer } from './server'; @@ -70,29 +71,60 @@ const del = async (req: express.Request, res: express.Response) => { }); }; +const redactHeaders = (headers: Record) => { + const hiddenHeaders = /auth|cookie|key|token/i; + const filtered = { ...headers }; + Object.keys(filtered).forEach((key) => { + if (hiddenHeaders.test(key)) { + filtered[key] = '[REDACTED]'; + } + }); + return filtered; +}; + export const streamableHTTPApp = ({ clientOptions = {}, mcpOptions, - debug, }: { clientOptions?: ClientOptions; mcpOptions: McpOptions; - debug: boolean; }): express.Express => { const app = express(); app.set('query parser', 'extended'); app.use(express.json()); - - if (debug) { - morganBody(app, { - logAllReqHeader: true, - logAllResHeader: true, - logRequestBody: true, - logResponseBody: true, - }); - } else { - app.use(morgan('combined')); - } + app.use( + pinoHttp({ + logger: getLogger(), + customLogLevel: (req, res) => { + if (res.statusCode >= 500) { + return 'error'; + } else if (res.statusCode >= 400) { + return 'warn'; + } + return 'info'; + }, + customSuccessMessage: function (req, res) { + return `Request ${req.method} to ${req.url} completed with status ${res.statusCode}`; + }, + customErrorMessage: function (req, res, err) { + return `Request ${req.method} to ${req.url} errored with status ${res.statusCode}`; + }, + serializers: { + req: pino.stdSerializers.wrapRequestSerializer((req) => { + return { + ...req, + headers: redactHeaders(req.raw.headers), + }; + }), + res: pino.stdSerializers.wrapResponseSerializer((res) => { + return { + ...res, + headers: redactHeaders(res.headers), + }; + }), + }, + }), + ); app.get('/health', async (req: express.Request, res: express.Response) => { res.status(200).send('OK'); @@ -106,22 +138,22 @@ export const streamableHTTPApp = ({ export const launchStreamableHTTPServer = async ({ mcpOptions, - debug, port, }: { mcpOptions: McpOptions; - debug: boolean; port: number | string | undefined; }) => { - const app = streamableHTTPApp({ mcpOptions, debug }); + const app = streamableHTTPApp({ mcpOptions }); const server = app.listen(port); const address = server.address(); + const logger = getLogger(); + if (typeof address === 'string') { - console.error(`MCP Server running on streamable HTTP at ${address}`); + logger.info(`MCP Server running on streamable HTTP at ${address}`); } else if (address !== null) { - console.error(`MCP Server running on streamable HTTP on port ${address.port}`); + logger.info(`MCP Server running on streamable HTTP on port ${address.port}`); } else { - console.error(`MCP Server running on streamable HTTP on port ${port}`); + logger.info(`MCP Server running on streamable HTTP on port ${port}`); } }; diff --git a/packages/mcp-server/src/index.ts b/packages/mcp-server/src/index.ts index 654d25cf..5bca4a60 100644 --- a/packages/mcp-server/src/index.ts +++ b/packages/mcp-server/src/index.ts @@ -5,15 +5,20 @@ import { McpOptions, parseCLIOptions } from './options'; import { launchStdioServer } from './stdio'; import { launchStreamableHTTPServer } from './http'; import type { McpTool } from './types'; +import { configureLogger, getLogger } from './logger'; async function main() { const options = parseOptionsOrError(); + configureLogger({ + level: options.debug ? 'debug' : 'info', + pretty: options.logFormat === 'pretty', + }); const selectedTools = await selectToolsOrError(options); - console.error( - `MCP Server starting with ${selectedTools.length} tools:`, - selectedTools.map((e) => e.tool.name), + getLogger().info( + { tools: selectedTools.map((e) => e.tool.name) }, + `MCP Server starting with ${selectedTools.length} tools`, ); switch (options.transport) { @@ -23,7 +28,6 @@ async function main() { case 'http': await launchStreamableHTTPServer({ mcpOptions: options, - debug: options.debug, port: options.socket ?? options.port, }); break; @@ -32,7 +36,8 @@ async function main() { if (require.main === module) { main().catch((error) => { - console.error('Fatal error in main():', error); + // Logger might not be initialized yet + console.error('Fatal error in main()', error); process.exit(1); }); } @@ -41,7 +46,8 @@ function parseOptionsOrError() { try { return parseCLIOptions(); } catch (error) { - console.error('Error parsing options:', error); + // Logger is initialized after options, so use console.error here + console.error('Error parsing options', error); process.exit(1); } } @@ -50,16 +56,12 @@ async function selectToolsOrError(options: McpOptions): Promise { try { const includedTools = selectTools(options); if (includedTools.length === 0) { - console.error('No tools match the provided filters.'); + getLogger().error('No tools match the provided filters'); process.exit(1); } return includedTools; } catch (error) { - if (error instanceof Error) { - console.error('Error filtering tools:', error.message); - } else { - console.error('Error filtering tools:', error); - } + getLogger().error({ error }, 'Error filtering tools'); process.exit(1); } } diff --git a/packages/mcp-server/src/instructions.ts b/packages/mcp-server/src/instructions.ts index 3e2dd699..2cfce0f5 100644 --- a/packages/mcp-server/src/instructions.ts +++ b/packages/mcp-server/src/instructions.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { readEnv } from './util'; +import { getLogger } from './logger'; const INSTRUCTIONS_CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes @@ -50,7 +51,7 @@ async function fetchLatestInstructions(stainlessApiKey: string | undefined): Pro let instructions: string | undefined; if (!response.ok) { - console.warn( + getLogger().warn( 'Warning: failed to retrieve MCP server instructions. Proceeding with default instructions...', ); diff --git a/packages/mcp-server/src/logger.ts b/packages/mcp-server/src/logger.ts new file mode 100644 index 00000000..29dab11c --- /dev/null +++ b/packages/mcp-server/src/logger.ts @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { pino, type Level, type Logger } from 'pino'; +import pretty from 'pino-pretty'; + +let _logger: Logger | undefined; + +export function configureLogger({ level, pretty: usePretty }: { level: Level; pretty: boolean }): void { + _logger = pino( + { + level, + timestamp: pino.stdTimeFunctions.isoTime, + formatters: { + level(label) { + return { level: label }; + }, + }, + }, + usePretty ? pretty({ colorize: true, levelFirst: true, destination: 2 }) : process.stderr, + ); +} + +export function getLogger(): Logger { + if (!_logger) { + throw new Error('Logger has not been configured. Call configureLogger() before using the logger.'); + } + return _logger; +} diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index 069b8811..b9e8e8a6 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -8,6 +8,7 @@ import { readEnv } from './util'; export type CLIOptions = McpOptions & { debug: boolean; + logFormat: 'json' | 'pretty'; transport: 'stdio' | 'http'; port: number | undefined; socket: string | undefined; @@ -52,6 +53,11 @@ export function parseCLIOptions(): CLIOptions { "Where to run code execution in code tool; 'stainless-sandbox' will execute code in Stainless-hosted sandboxes whereas 'local' will execute code locally on the MCP server machine.", }) .option('debug', { type: 'boolean', description: 'Enable debug logging' }) + .option('log-format', { + type: 'string', + choices: ['json', 'pretty'], + description: 'Format for log output; defaults to json unless tty is detected', + }) .option('no-tools', { type: 'string', array: true, @@ -97,6 +103,10 @@ export function parseCLIOptions(): CLIOptions { const includeDocsTools = shouldIncludeToolType('docs'); const transport = argv.transport as 'stdio' | 'http'; + const logFormat = + argv.logFormat ? (argv.logFormat as 'json' | 'pretty') + : process.stderr.isTTY ? 'pretty' + : 'json'; return { ...(includeCodeTool !== undefined && { includeCodeTool }), @@ -108,6 +118,7 @@ export function parseCLIOptions(): CLIOptions { codeBlockedMethods: argv.codeBlockedMethods, codeExecutionMode: argv.codeExecutionMode as McpCodeExecutionMode, transport, + logFormat, port: argv.port, socket: argv.socket, }; diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 8768a039..44a5f7ea 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -21,7 +21,7 @@ export const newMcpServer = async (stainlessApiKey: string | undefined) => new McpServer( { name: 'lithic_api', - version: '0.130.0', + version: '0.131.0', }, { instructions: await getInstructions(stainlessApiKey), diff --git a/packages/mcp-server/src/stdio.ts b/packages/mcp-server/src/stdio.ts index ceccaed3..e8bcbb19 100644 --- a/packages/mcp-server/src/stdio.ts +++ b/packages/mcp-server/src/stdio.ts @@ -1,6 +1,7 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { McpOptions } from './options'; import { initMcpServer, newMcpServer } from './server'; +import { getLogger } from './logger'; export const launchStdioServer = async (mcpOptions: McpOptions) => { const server = await newMcpServer(mcpOptions.stainlessApiKey); @@ -9,5 +10,5 @@ export const launchStdioServer = async (mcpOptions: McpOptions) => { const transport = new StdioServerTransport(); await server.connect(transport); - console.error('MCP Server running on stdio'); + getLogger().info('MCP Server running on stdio'); }; diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index fe102775..14529bc9 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -329,10 +329,10 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== -"@hono/node-server@^1.19.7": - version "1.19.9" - resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.19.9.tgz#8f37119b1acf283fd3f6035f3d1356fdb97a09ac" - integrity sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw== +"@hono/node-server@^1.19.9": + version "1.19.10" + resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.19.10.tgz#e230fbb7fb31891cafc653d01deee03f437dd66b" + integrity sha512-hZ7nOssGqRgyV3FVVQdfi+U4q02uB23bpnYpdvNXkYTRRyWx84b7yf1ans+dnJ/7h41sGL3CeQTfO+ZGxuO+Iw== "@humanwhocodes/config-array@^0.13.0": version "0.13.0" @@ -741,12 +741,12 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@modelcontextprotocol/sdk@^1.25.2": - version "1.25.2" - resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.25.2.tgz#2284560b4e044b4ce5f328ee180931110cb8c5cf" - integrity sha512-LZFeo4F9M5qOhC/Uc1aQSrBHxMrvxett+9KLHt7OhcExtoiRN9DKgbZffMP/nxjutWDQpfMDfP3nkHI4X9ijww== +"@modelcontextprotocol/sdk@^1.26.0": + version "1.27.1" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.27.1.tgz#a602cf823bf8a68e13e7112f50aeb02b09fb83b9" + integrity sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA== dependencies: - "@hono/node-server" "^1.19.7" + "@hono/node-server" "^1.19.9" ajv "^8.17.1" ajv-formats "^3.0.1" content-type "^1.0.5" @@ -754,14 +754,15 @@ cross-spawn "^7.0.5" eventsource "^3.0.2" eventsource-parser "^3.0.0" - express "^5.0.1" - express-rate-limit "^7.5.0" - jose "^6.1.1" + express "^5.2.1" + express-rate-limit "^8.2.1" + hono "^4.11.4" + jose "^6.1.3" json-schema-typed "^8.0.2" pkce-challenge "^5.0.0" raw-body "^3.0.0" zod "^3.25 || ^4.0" - zod-to-json-schema "^3.25.0" + zod-to-json-schema "^3.25.1" "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -784,6 +785,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@pinojs/redact@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@pinojs/redact/-/redact-0.4.0.tgz#c3de060dd12640dcc838516aa2a6803cc7b2e9d6" + integrity sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg== + "@pkgr/core@^0.2.9": version "0.2.9" resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" @@ -808,6 +814,11 @@ dependencies: "@sinonjs/commons" "^3.0.0" +"@stablelib/base64@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/base64/-/base64-1.0.1.tgz#bdfc1c6d3a62d7a3b7bbc65b6cce1bb4561641be" + integrity sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ== + "@ts-morph/common@~0.20.0": version "0.20.0" resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.20.0.tgz#3f161996b085ba4519731e4d24c35f6cba5b80af" @@ -886,6 +897,11 @@ dependencies: "@types/node" "*" +"@types/cookie-parser@^1.4.10": + version "1.4.10" + resolved "https://registry.yarnpkg.com/@types/cookie-parser/-/cookie-parser-1.4.10.tgz#a045272a383a30597a01955d4f9c790018f214e4" + integrity sha512-B4xqkqfZ8Wek+rCOeRxsjMS9OgvzebEzzLYw7NHYuvzb7IdxOkI0ZHGgeEBX4PUM7QGVvNSK60T3OvWj3YfBRg== + "@types/cors@^2.8.19": version "2.8.19" resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.19.tgz#d93ea2673fd8c9f697367f5eeefc2bbfa94f0342" @@ -1219,6 +1235,11 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" @@ -1474,6 +1495,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^2.0.7: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + commander@^13.1.0: version "13.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" @@ -1499,12 +1525,25 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +cookie-parser@^1.4.6: + version "1.4.7" + resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.7.tgz#e2125635dfd766888ffe90d60c286404fa0e7b26" + integrity sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw== + dependencies: + cookie "0.7.2" + cookie-signature "1.0.6" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + cookie-signature@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793" integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== -cookie@^0.7.1: +cookie@0.7.2, cookie@^0.7.1: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== @@ -1544,6 +1583,11 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.5: shebang-command "^2.0.0" which "^2.0.1" +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7, debug@^4.4.0, debug@^4.4.3: version "4.4.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" @@ -1627,6 +1671,13 @@ encodeurl@^2.0.0: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== +end-of-stream@^1.1.0: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + error-ex@^1.3.1: version "1.3.4" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" @@ -1839,12 +1890,14 @@ expect@^29.0.0, expect@^29.7.0: jest-message-util "^29.7.0" jest-util "^29.7.0" -express-rate-limit@^7.5.0: - version "7.5.1" - resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.1.tgz#8c3a42f69209a3a1c969890070ece9e20a879dec" - integrity sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw== +express-rate-limit@^8.2.1: + version "8.2.1" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-8.2.1.tgz#ec75fdfe280ecddd762b8da8784c61bae47d7f7f" + integrity sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g== + dependencies: + ip-address "10.0.1" -express@^5.0.1, express@^5.1.0: +express@^5.1.0, express@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/express/-/express-5.2.1.tgz#8f21d15b6d327f92b4794ecf8cb08a72f956ac04" integrity sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw== @@ -1887,6 +1940,11 @@ external-editor@^3.1.0: iconv-lite "^0.4.24" tmp "^0.0.33" +fast-copy@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-4.0.2.tgz#57f14115e1edbec274f69090072a480aa29cbedd" + integrity sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1918,6 +1976,16 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + +fast-sha256@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-sha256/-/fast-sha256-1.3.0.tgz#7916ba2054eeb255982608cccd0f6660c79b7ae6" + integrity sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ== + fast-uri@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" @@ -2180,6 +2248,16 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" +help-me@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" + integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== + +hono@^4.11.4: + version "4.12.4" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.12.4.tgz#fcfb5a064b90d5203dd41231e0d5a67262fc1729" + integrity sha512-ooiZW1Xy8rQ4oELQ++otI2T9DsKpV0M6c6cO6JGx4RTfav9poFFLlet9UMXHZnoM1yG0HWGlQLswBGX3RZmHtg== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -2264,6 +2342,11 @@ inherits@2, inherits@^2.0.3, inherits@~2.0.4: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ip-address@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.0.1.tgz#a8180b783ce7788777d796286d61bce4276818ed" + integrity sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA== + ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -2739,11 +2822,16 @@ jest@^29.4.0: import-local "^3.0.2" jest-cli "^29.7.0" -jose@^6.1.1: +jose@^6.1.3: version "6.1.3" resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.3.tgz#8453d7be88af7bb7d64a0481d6a35a0145ba3ea5" integrity sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ== +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + "jq-web@https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz": version "0.8.8" resolved "https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz#7849ef64bdfc28f70cbfc9888f886860e96da10d" @@ -2847,6 +2935,11 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +"lithic@file:../../dist": + version "0.130.0" + dependencies: + standardwebhooks "^1.0.0" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -3040,6 +3133,11 @@ object-inspect@^1.13.3: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + on-finished@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -3047,7 +3145,7 @@ on-finished@^2.4.1: dependencies: ee-first "1.1.1" -once@^1.3.0, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -3187,6 +3285,64 @@ picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pino-abstract-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz#b21e5f33a297e8c4c915c62b3ce5dd4a87a52c23" + integrity sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg== + dependencies: + split2 "^4.0.0" + +pino-http@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-11.0.0.tgz#ebadef4694fc59aadab9be7e5939aea625b4615f" + integrity sha512-wqg5XIAGRRIWtTk8qPGxkbrfiwEWz1lgedVLvhLALudKXvg1/L2lTFgTGPJ4Z2e3qcRmxoFxDuSdMdMGNM6I1g== + dependencies: + get-caller-file "^2.0.5" + pino "^10.0.0" + pino-std-serializers "^7.0.0" + process-warning "^5.0.0" + +pino-pretty@^13.1.3: + version "13.1.3" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-13.1.3.tgz#2274cccda925dd355c104079a5029f6598d0381b" + integrity sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^4.0.0" + fast-safe-stringify "^2.1.1" + help-me "^5.0.0" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^3.0.0" + pump "^3.0.0" + secure-json-parse "^4.0.0" + sonic-boom "^4.0.1" + strip-json-comments "^5.0.2" + +pino-std-serializers@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz#a7b0cd65225f29e92540e7853bd73b07479893fc" + integrity sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw== + +pino@^10.0.0, pino@^10.3.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/pino/-/pino-10.3.1.tgz#6552c8f8d8481844c9e452e7bf0be90bff1939ce" + integrity sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg== + dependencies: + "@pinojs/redact" "^0.4.0" + atomic-sleep "^1.0.0" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^3.0.0" + pino-std-serializers "^7.0.0" + process-warning "^5.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + sonic-boom "^4.0.1" + thread-stream "^4.0.0" + pirates@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" @@ -3235,6 +3391,11 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: ansi-styles "^5.0.0" react-is "^18.0.0" +process-warning@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-5.0.0.tgz#566e0bf79d1dff30a72d8bbbe9e8ecefe8d378d7" + integrity sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA== + prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -3251,6 +3412,14 @@ proxy-addr@^2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +pump@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.4.tgz#1f313430527fa8b905622ebd22fe1444e757ab3c" + integrity sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -3273,6 +3442,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + range-parser@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -3302,6 +3476,11 @@ readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -3378,11 +3557,21 @@ safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-stable-stringify@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +secure-json-parse@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-4.1.0.tgz#4f1ab41c67a13497ea1b9131bb4183a22865477c" + integrity sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA== + semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" @@ -3497,6 +3686,13 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +sonic-boom@^4.0.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.1.tgz#28598250df4899c0ac572d7e2f0460690ba6a030" + integrity sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q== + dependencies: + atomic-sleep "^1.0.0" + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -3510,6 +3706,11 @@ source-map@^0.6.0, source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -3522,6 +3723,14 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +standardwebhooks@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/standardwebhooks/-/standardwebhooks-1.0.0.tgz#5faa23ceacbf9accd344361101d9e3033b64324f" + integrity sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg== + dependencies: + "@stablelib/base64" "^1.0.0" + fast-sha256 "^1.3.0" + statuses@^2.0.1, statuses@^2.0.2, statuses@~2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.2.tgz#8f75eecef765b5e1cfcdc080da59409ed424e382" @@ -3585,6 +3794,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-5.0.3.tgz#b7304249dd402ee67fd518ada993ab3593458bcf" + integrity sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw== + superstruct@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" @@ -3630,6 +3844,13 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +thread-stream@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-4.0.0.tgz#732f007c24da7084f729d6e3a7e3f5934a7380b7" + integrity sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA== + dependencies: + real-require "^0.2.0" + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -3933,7 +4154,7 @@ yoctocolors-cjs@^2.1.2: resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== -zod-to-json-schema@^3.24.5, zod-to-json-schema@^3.24.6, zod-to-json-schema@^3.25.0: +zod-to-json-schema@^3.24.5, zod-to-json-schema@^3.24.6, zod-to-json-schema@^3.25.1: version "3.25.1" resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz#7f24962101a439ddade2bf1aeab3c3bfec7d84ba" integrity sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA== diff --git a/src/resources/account-holders/account-holders.ts b/src/resources/account-holders/account-holders.ts index 43e56e22..39d12907 100644 --- a/src/resources/account-holders/account-holders.ts +++ b/src/resources/account-holders/account-holders.ts @@ -62,15 +62,6 @@ export class AccountHolders extends APIResource { * nature_of_business: 'Software company selling solutions to the restaurant industry', * tos_timestamp: '2022-03-08T08:00:00Z', * workflow: 'KYB_BYO', - * beneficial_owner_entities: [ - * { - * address: { ... }, - * dba_business_name: 'MHoldings', - * government_id: '98-7654321', - * legal_business_name: 'Majority Holdings LLC', - * phone_numbers: ['+15555555555'], - * }, - * ], * kyb_passed_timestamp: '2022-03-08T08:00:00Z', * naics_code: '541512', * website_url: 'https://www.mybusiness.com', @@ -331,11 +322,6 @@ export interface AccountHolder { */ account_token?: string; - /** - * @deprecated Deprecated. - */ - beneficial_owner_entities?: Array; - /** * Only present when user_type == "BUSINESS". You must submit a list of all direct * and indirect individuals with 25% or more ownership in the company. A maximum of @@ -468,48 +454,6 @@ export interface AccountHolder { } export namespace AccountHolder { - export interface BeneficialOwnerEntity { - /** - * Business's physical address - PO boxes, UPS drops, and FedEx drops are not - * acceptable; APO/FPO are acceptable. - */ - address: Shared.Address; - - /** - * Any name that the business operates under that is not its legal business name - * (if applicable). - */ - dba_business_name: string; - - /** - * Globally unique identifier for the entity. - */ - entity_token: string; - - /** - * Government-issued identification number. US Federal Employer Identification - * Numbers (EIN) are currently supported, entered as full nine-digits, with or - * without hyphens. - */ - government_id: string; - - /** - * Legal (formal) business name. - */ - legal_business_name: string; - - /** - * One or more of the business's phone number(s), entered as a list in E.164 - * format. - */ - phone_numbers: Array; - - /** - * Parent company name (if applicable). - */ - parent_company?: string; - } - /** * Information about an individual associated with an account holder. A subset of * the information provided via KYC. For example, we do not return the government @@ -808,11 +752,6 @@ export interface KYB { */ workflow: 'KYB_BASIC' | 'KYB_BYO'; - /** - * @deprecated Deprecated. - */ - beneficial_owner_entities?: Array; - /** * A user provided id that can be used to link an account holder with an external * system @@ -977,43 +916,6 @@ export namespace KYB { */ phone_number?: string; } - - export interface BeneficialOwnerEntity { - /** - * Business's physical address - PO boxes, UPS drops, and FedEx drops are not - * acceptable; APO/FPO are acceptable. - */ - address: Shared.Address; - - /** - * Government-issued identification number. US Federal Employer Identification - * Numbers (EIN) are currently supported, entered as full nine-digits, with or - * without hyphens. - */ - government_id: string; - - /** - * Legal (formal) business name. - */ - legal_business_name: string; - - /** - * One or more of the business's phone number(s), entered as a list in E.164 - * format. - */ - phone_numbers: Array; - - /** - * Any name that the business operates under that is not its legal business name - * (if applicable). - */ - dba_business_name?: string; - - /** - * Parent company name (if applicable). - */ - parent_company?: string; - } } export interface KYBBusinessEntity { @@ -1330,11 +1232,6 @@ export namespace AccountHolderUpdateResponse { */ account_token?: string; - /** - * Deprecated. - */ - beneficial_owner_entities?: Array; - /** * Only present when user_type == "BUSINESS". You must submit a list of all direct * and indirect individuals with 25% or more ownership in the company. A maximum of @@ -1890,11 +1787,6 @@ export interface AccountHolderSimulateEnrollmentReviewResponse { */ account_token?: string; - /** - * Deprecated. - */ - beneficial_owner_entities?: Array; - /** * Only present when user_type == "BUSINESS". You must submit a list of all direct * and indirect individuals with 25% or more ownership in the company. A maximum of @@ -2406,11 +2298,6 @@ export declare namespace AccountHolderCreateParams { */ workflow: 'KYB_BASIC' | 'KYB_BYO'; - /** - * @deprecated Deprecated. - */ - beneficial_owner_entities?: Array; - /** * A user provided id that can be used to link an account holder with an external * system @@ -2575,43 +2462,6 @@ export declare namespace AccountHolderCreateParams { */ phone_number?: string; } - - export interface BeneficialOwnerEntity { - /** - * Business's physical address - PO boxes, UPS drops, and FedEx drops are not - * acceptable; APO/FPO are acceptable. - */ - address: Shared.Address; - - /** - * Government-issued identification number. US Federal Employer Identification - * Numbers (EIN) are currently supported, entered as full nine-digits, with or - * without hyphens. - */ - government_id: string; - - /** - * Legal (formal) business name. - */ - legal_business_name: string; - - /** - * One or more of the business's phone number(s), entered as a list in E.164 - * format. - */ - phone_numbers: Array; - - /** - * Any name that the business operates under that is not its legal business name - * (if applicable). - */ - dba_business_name?: string; - - /** - * Parent company name (if applicable). - */ - parent_company?: string; - } } export interface KYBDelegated { @@ -2958,11 +2808,6 @@ export type AccountHolderUpdateParams = export declare namespace AccountHolderUpdateParams { export interface KYBPatchRequest { - /** - * @deprecated Deprecated. - */ - beneficial_owner_entities?: Array; - /** * You must submit a list of all direct and indirect individuals with 25% or more * ownership in the company. A maximum of 4 beneficial owners can be submitted. If @@ -3016,48 +2861,6 @@ export declare namespace AccountHolderUpdateParams { } export namespace KYBPatchRequest { - export interface BeneficialOwnerEntity { - /** - * Globally unique identifier for an entity. - */ - entity_token: string; - - /** - * Business''s physical address - PO boxes, UPS drops, and FedEx drops are not - * acceptable; APO/FPO are acceptable. - */ - address?: AccountHoldersAPI.AddressUpdate; - - /** - * Any name that the business operates under that is not its legal business name - * (if applicable). - */ - dba_business_name?: string; - - /** - * Government-issued identification number. US Federal Employer Identification - * Numbers (EIN) are currently supported, entered as full nine-digits, with or - * without hyphens. - */ - government_id?: string; - - /** - * Legal (formal) business name. - */ - legal_business_name?: string; - - /** - * Parent company name (if applicable). - */ - parent_company?: string; - - /** - * One or more of the business's phone number(s), entered as a list in E.164 - * format. - */ - phone_numbers?: Array; - } - /** * Individuals associated with a KYB application. Phone number is optional. */ diff --git a/src/resources/account-holders/entities.ts b/src/resources/account-holders/entities.ts index fde363d0..3ca8796d 100644 --- a/src/resources/account-holders/entities.ts +++ b/src/resources/account-holders/entities.ts @@ -8,8 +8,8 @@ import { path } from '../../internal/utils/path'; export class Entities extends APIResource { /** - * Create a new beneficial owner or replace the control person entity on an - * existing KYB account holder. This endpoint is only applicable for account + * Create a new beneficial owner individual or replace the control person entity on + * an existing KYB account holder. This endpoint is only applicable for account * holders enrolled through a KYB workflow with the Persona KYB provider. A new * control person can only replace the existing one. A maximum of 4 beneficial * owners can be associated with an account holder. @@ -46,8 +46,8 @@ export class Entities extends APIResource { } /** - * Deactivate a beneficial owner entity on an existing KYB account holder. Only - * beneficial owner entities can be deactivated. + * Deactivate a beneficial owner individual on an existing KYB account holder. Only + * beneficial owner individuals can be deactivated. * * @example * ```ts diff --git a/src/resources/auth-rules/auth-rules.ts b/src/resources/auth-rules/auth-rules.ts index 11dcf45a..4d3b2a36 100644 --- a/src/resources/auth-rules/auth-rules.ts +++ b/src/resources/auth-rules/auth-rules.ts @@ -6,6 +6,7 @@ import { AuthRule, AuthRuleCondition, AuthRulesCursorPage, + BacktestStats, Conditional3DSActionParameters, ConditionalACHActionParameters, ConditionalAttribute, @@ -16,7 +17,7 @@ import { ConditionalValue, EventStream, MerchantLockParameters, - RuleStats, + ReportStats, V2, V2CreateParams, V2DraftParams, @@ -44,6 +45,7 @@ export declare namespace AuthRules { V2 as V2, type AuthRule as AuthRule, type AuthRuleCondition as AuthRuleCondition, + type BacktestStats as BacktestStats, type Conditional3DSActionParameters as Conditional3DSActionParameters, type ConditionalACHActionParameters as ConditionalACHActionParameters, type ConditionalAttribute as ConditionalAttribute, @@ -54,7 +56,7 @@ export declare namespace AuthRules { type ConditionalValue as ConditionalValue, type EventStream as EventStream, type MerchantLockParameters as MerchantLockParameters, - type RuleStats as RuleStats, + type ReportStats as ReportStats, type VelocityLimitParams as VelocityLimitParams, type VelocityLimitPeriod as VelocityLimitPeriod, type V2ListResultsResponse as V2ListResultsResponse, diff --git a/src/resources/auth-rules/index.ts b/src/resources/auth-rules/index.ts index dcb1e7f9..2e33e3c2 100644 --- a/src/resources/auth-rules/index.ts +++ b/src/resources/auth-rules/index.ts @@ -5,6 +5,7 @@ export { V2, type AuthRule, type AuthRuleCondition, + type BacktestStats, type Conditional3DSActionParameters, type ConditionalACHActionParameters, type ConditionalAttribute, @@ -15,7 +16,7 @@ export { type ConditionalValue, type EventStream, type MerchantLockParameters, - type RuleStats, + type ReportStats, type VelocityLimitParams, type VelocityLimitPeriod, type V2ListResultsResponse, diff --git a/src/resources/auth-rules/v2/backtests.ts b/src/resources/auth-rules/v2/backtests.ts index a9562a9e..20f71d75 100644 --- a/src/resources/auth-rules/v2/backtests.ts +++ b/src/resources/auth-rules/v2/backtests.ts @@ -88,9 +88,9 @@ export interface BacktestResults { export namespace BacktestResults { export interface Results { - current_version?: V2API.RuleStats | null; + current_version?: V2API.BacktestStats | null; - draft_version?: V2API.RuleStats | null; + draft_version?: V2API.BacktestStats | null; } export interface SimulationParameters { diff --git a/src/resources/auth-rules/v2/index.ts b/src/resources/auth-rules/v2/index.ts index 0166be00..f35dc3a5 100644 --- a/src/resources/auth-rules/v2/index.ts +++ b/src/resources/auth-rules/v2/index.ts @@ -11,6 +11,7 @@ export { V2, type AuthRule, type AuthRuleCondition, + type BacktestStats, type Conditional3DSActionParameters, type ConditionalACHActionParameters, type ConditionalAttribute, @@ -21,7 +22,7 @@ export { type ConditionalValue, type EventStream, type MerchantLockParameters, - type RuleStats, + type ReportStats, type VelocityLimitParams, type VelocityLimitPeriod, type V2ListResultsResponse, diff --git a/src/resources/auth-rules/v2/v2.ts b/src/resources/auth-rules/v2/v2.ts index 2d1c157f..c096b249 100644 --- a/src/resources/auth-rules/v2/v2.ts +++ b/src/resources/auth-rules/v2/v2.ts @@ -324,6 +324,60 @@ export interface AuthRuleCondition { value: ConditionalValue; } +export interface BacktestStats { + /** + * The total number of historical transactions approved by this rule during the + * backtest period, or the number of transactions that would have been approved if + * the rule was evaluated in shadow mode. + */ + approved?: number; + + /** + * The total number of historical transactions challenged by this rule during the + * backtest period, or the number of transactions that would have been challenged + * if the rule was evaluated in shadow mode. Currently applicable only for 3DS Auth + * Rules. + */ + challenged?: number; + + /** + * The total number of historical transactions declined by this rule during the + * backtest period, or the number of transactions that would have been declined if + * the rule was evaluated in shadow mode. + */ + declined?: number; + + /** + * Example events and their outcomes. + */ + examples?: Array; + + /** + * The version of the rule, this is incremented whenever the rule's parameters + * change. + */ + version?: number; +} + +export namespace BacktestStats { + export interface Example { + /** + * The decision made by the rule for this event. + */ + decision?: 'APPROVED' | 'DECLINED' | 'CHALLENGED'; + + /** + * The event token. + */ + event_token?: string; + + /** + * The timestamp of the event. + */ + timestamp?: string; + } +} + export interface Conditional3DSActionParameters { /** * The action to take if the conditions are met. @@ -388,13 +442,13 @@ export interface ConditionalACHActionParameters { /** * The action to take if the conditions are met. */ - action: ConditionalACHActionParameters.ApproveAction | ConditionalACHActionParameters.ReturnAction; + action: ConditionalACHActionParameters.ApproveActionACH | ConditionalACHActionParameters.ReturnAction; conditions: Array; } export namespace ConditionalACHActionParameters { - export interface ApproveAction { + export interface ApproveActionACH { /** * Approve the ACH transaction */ @@ -720,14 +774,14 @@ export interface ConditionalTokenizationActionParameters { * The action to take if the conditions are met. */ action: - | ConditionalTokenizationActionParameters.DeclineAction + | ConditionalTokenizationActionParameters.DeclineActionTokenization | ConditionalTokenizationActionParameters.RequireTfaAction; conditions: Array; } export namespace ConditionalTokenizationActionParameters { - export interface DeclineAction { + export interface DeclineActionTokenization { /** * Decline the tokenization request */ @@ -906,50 +960,65 @@ export namespace MerchantLockParameters { } } -export interface RuleStats { +export interface ReportStats { /** - * The total number of historical transactions approved by this rule during the - * relevant period, or the number of transactions that would have been approved if - * the rule was evaluated in shadow mode. + * A mapping of action types to the number of times that action was returned by + * this rule during the relevant period. Actions are the possible outcomes of a + * rule evaluation, such as DECLINE, CHALLENGE, REQUIRE_TFA, etc. In case rule + * didn't trigger any action, it's counted under NO_ACTION key. + */ + action_counts?: { [key: string]: number }; + + /** + * @deprecated The total number of historical transactions approved by this rule + * during the relevant period, or the number of transactions that would have been + * approved if the rule was evaluated in shadow mode. */ approved?: number; /** - * The total number of historical transactions challenged by this rule during the - * relevant period, or the number of transactions that would have been challenged - * if the rule was evaluated in shadow mode. Currently applicable only for 3DS Auth - * Rules. + * @deprecated The total number of historical transactions challenged by this rule + * during the relevant period, or the number of transactions that would have been + * challenged if the rule was evaluated in shadow mode. Currently applicable only + * for 3DS Auth Rules. */ challenged?: number; /** - * The total number of historical transactions declined by this rule during the - * relevant period, or the number of transactions that would have been declined if - * the rule was evaluated in shadow mode. + * @deprecated The total number of historical transactions declined by this rule + * during the relevant period, or the number of transactions that would have been + * declined if the rule was evaluated in shadow mode. */ declined?: number; /** * Example events and their outcomes. */ - examples?: Array; - - /** - * The version of the rule, this is incremented whenever the rule's parameters - * change. - */ - version?: number; + examples?: Array; } -export namespace RuleStats { +export namespace ReportStats { export interface Example { /** - * Whether the rule would have approved the request. + * The actions taken by the rule for this event. + */ + actions?: Array< + | Example.DeclineActionAuthorization + | Example.ChallengeActionAuthorization + | Example.ResultAuthentication3DSAction + | Example.DeclineActionTokenization + | Example.RequireTfaAction + | Example.ApproveActionACH + | Example.ReturnAction + >; + + /** + * @deprecated Whether the rule would have approved the request. */ approved?: boolean; /** - * The decision made by the rule for this event. + * @deprecated The decision made by the rule for this event. */ decision?: 'APPROVED' | 'DECLINED' | 'CHALLENGED'; @@ -963,6 +1032,225 @@ export namespace RuleStats { */ timestamp?: string; } + + export namespace Example { + export interface DeclineActionAuthorization { + /** + * The detailed result code explaining the specific reason for the decline + */ + code: + | 'ACCOUNT_DAILY_SPEND_LIMIT_EXCEEDED' + | 'ACCOUNT_DELINQUENT' + | 'ACCOUNT_INACTIVE' + | 'ACCOUNT_LIFETIME_SPEND_LIMIT_EXCEEDED' + | 'ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED' + | 'ACCOUNT_PAUSED' + | 'ACCOUNT_UNDER_REVIEW' + | 'ADDRESS_INCORRECT' + | 'APPROVED' + | 'AUTH_RULE_ALLOWED_COUNTRY' + | 'AUTH_RULE_ALLOWED_MCC' + | 'AUTH_RULE_BLOCKED_COUNTRY' + | 'AUTH_RULE_BLOCKED_MCC' + | 'AUTH_RULE' + | 'CARD_CLOSED' + | 'CARD_CRYPTOGRAM_VALIDATION_FAILURE' + | 'CARD_EXPIRED' + | 'CARD_EXPIRY_DATE_INCORRECT' + | 'CARD_INVALID' + | 'CARD_NOT_ACTIVATED' + | 'CARD_PAUSED' + | 'CARD_PIN_INCORRECT' + | 'CARD_RESTRICTED' + | 'CARD_SECURITY_CODE_INCORRECT' + | 'CARD_SPEND_LIMIT_EXCEEDED' + | 'CONTACT_CARD_ISSUER' + | 'CUSTOMER_ASA_TIMEOUT' + | 'CUSTOM_ASA_RESULT' + | 'DECLINED' + | 'DO_NOT_HONOR' + | 'DRIVER_NUMBER_INVALID' + | 'FORMAT_ERROR' + | 'INSUFFICIENT_FUNDING_SOURCE_BALANCE' + | 'INSUFFICIENT_FUNDS' + | 'LITHIC_SYSTEM_ERROR' + | 'LITHIC_SYSTEM_RATE_LIMIT' + | 'MALFORMED_ASA_RESPONSE' + | 'MERCHANT_INVALID' + | 'MERCHANT_LOCKED_CARD_ATTEMPTED_ELSEWHERE' + | 'MERCHANT_NOT_PERMITTED' + | 'OVER_REVERSAL_ATTEMPTED' + | 'PIN_BLOCKED' + | 'PROGRAM_CARD_SPEND_LIMIT_EXCEEDED' + | 'PROGRAM_SUSPENDED' + | 'PROGRAM_USAGE_RESTRICTION' + | 'REVERSAL_UNMATCHED' + | 'SECURITY_VIOLATION' + | 'SINGLE_USE_CARD_REATTEMPTED' + | 'SUSPECTED_FRAUD' + | 'TRANSACTION_INVALID' + | 'TRANSACTION_NOT_PERMITTED_TO_ACQUIRER_OR_TERMINAL' + | 'TRANSACTION_NOT_PERMITTED_TO_ISSUER_OR_CARDHOLDER' + | 'TRANSACTION_PREVIOUSLY_COMPLETED' + | 'UNAUTHORIZED_MERCHANT' + | 'VEHICLE_NUMBER_INVALID' + | 'CARDHOLDER_CHALLENGED' + | 'CARDHOLDER_CHALLENGE_FAILED'; + + type: 'DECLINE'; + } + + export interface ChallengeActionAuthorization { + type: 'CHALLENGE'; + } + + export interface ResultAuthentication3DSAction { + type: 'DECLINE' | 'CHALLENGE'; + } + + export interface DeclineActionTokenization { + /** + * Decline the tokenization request + */ + type: 'DECLINE'; + + /** + * Reason code for declining the tokenization request + */ + reason?: + | 'ACCOUNT_SCORE_1' + | 'DEVICE_SCORE_1' + | 'ALL_WALLET_DECLINE_REASONS_PRESENT' + | 'WALLET_RECOMMENDED_DECISION_RED' + | 'CVC_MISMATCH' + | 'CARD_EXPIRY_MONTH_MISMATCH' + | 'CARD_EXPIRY_YEAR_MISMATCH' + | 'CARD_INVALID_STATE' + | 'CUSTOMER_RED_PATH' + | 'INVALID_CUSTOMER_RESPONSE' + | 'NETWORK_FAILURE' + | 'GENERIC_DECLINE' + | 'DIGITAL_CARD_ART_REQUIRED'; + } + + export interface RequireTfaAction { + /** + * Require two-factor authentication for the tokenization request + */ + type: 'REQUIRE_TFA'; + + /** + * Reason code for requiring two-factor authentication + */ + reason?: + | 'WALLET_RECOMMENDED_TFA' + | 'SUSPICIOUS_ACTIVITY' + | 'DEVICE_RECENTLY_LOST' + | 'TOO_MANY_RECENT_ATTEMPTS' + | 'TOO_MANY_RECENT_TOKENS' + | 'TOO_MANY_DIFFERENT_CARDHOLDERS' + | 'OUTSIDE_HOME_TERRITORY' + | 'HAS_SUSPENDED_TOKENS' + | 'HIGH_RISK' + | 'ACCOUNT_SCORE_LOW' + | 'DEVICE_SCORE_LOW' + | 'CARD_STATE_TFA' + | 'HARDCODED_TFA' + | 'CUSTOMER_RULE_TFA' + | 'DEVICE_HOST_CARD_EMULATION'; + } + + export interface ApproveActionACH { + /** + * Approve the ACH transaction + */ + type: 'APPROVE'; + } + + export interface ReturnAction { + /** + * NACHA return code to use when returning the transaction. Note that the list of + * available return codes is subject to an allowlist configured at the program + * level + */ + code: + | 'R01' + | 'R02' + | 'R03' + | 'R04' + | 'R05' + | 'R06' + | 'R07' + | 'R08' + | 'R09' + | 'R10' + | 'R11' + | 'R12' + | 'R13' + | 'R14' + | 'R15' + | 'R16' + | 'R17' + | 'R18' + | 'R19' + | 'R20' + | 'R21' + | 'R22' + | 'R23' + | 'R24' + | 'R25' + | 'R26' + | 'R27' + | 'R28' + | 'R29' + | 'R30' + | 'R31' + | 'R32' + | 'R33' + | 'R34' + | 'R35' + | 'R36' + | 'R37' + | 'R38' + | 'R39' + | 'R40' + | 'R41' + | 'R42' + | 'R43' + | 'R44' + | 'R45' + | 'R46' + | 'R47' + | 'R50' + | 'R51' + | 'R52' + | 'R53' + | 'R61' + | 'R62' + | 'R67' + | 'R68' + | 'R69' + | 'R70' + | 'R71' + | 'R72' + | 'R73' + | 'R74' + | 'R75' + | 'R76' + | 'R77' + | 'R80' + | 'R81' + | 'R82' + | 'R83' + | 'R84' + | 'R85'; + + /** + * Return the ACH transaction + */ + type: 'RETURN'; + } + } } export interface VelocityLimitParams { @@ -1146,7 +1434,9 @@ export namespace V2ListResultsResponse { /** * Actions returned by the rule evaluation */ - actions: Array; + actions: Array< + AuthorizationResult.DeclineActionAuthorization | AuthorizationResult.ChallengeActionAuthorization + >; /** * The Auth Rule token @@ -1180,8 +1470,79 @@ export namespace V2ListResultsResponse { } export namespace AuthorizationResult { - export interface Action { - type: 'DECLINE' | 'CHALLENGE'; + export interface DeclineActionAuthorization { + /** + * The detailed result code explaining the specific reason for the decline + */ + code: + | 'ACCOUNT_DAILY_SPEND_LIMIT_EXCEEDED' + | 'ACCOUNT_DELINQUENT' + | 'ACCOUNT_INACTIVE' + | 'ACCOUNT_LIFETIME_SPEND_LIMIT_EXCEEDED' + | 'ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED' + | 'ACCOUNT_PAUSED' + | 'ACCOUNT_UNDER_REVIEW' + | 'ADDRESS_INCORRECT' + | 'APPROVED' + | 'AUTH_RULE_ALLOWED_COUNTRY' + | 'AUTH_RULE_ALLOWED_MCC' + | 'AUTH_RULE_BLOCKED_COUNTRY' + | 'AUTH_RULE_BLOCKED_MCC' + | 'AUTH_RULE' + | 'CARD_CLOSED' + | 'CARD_CRYPTOGRAM_VALIDATION_FAILURE' + | 'CARD_EXPIRED' + | 'CARD_EXPIRY_DATE_INCORRECT' + | 'CARD_INVALID' + | 'CARD_NOT_ACTIVATED' + | 'CARD_PAUSED' + | 'CARD_PIN_INCORRECT' + | 'CARD_RESTRICTED' + | 'CARD_SECURITY_CODE_INCORRECT' + | 'CARD_SPEND_LIMIT_EXCEEDED' + | 'CONTACT_CARD_ISSUER' + | 'CUSTOMER_ASA_TIMEOUT' + | 'CUSTOM_ASA_RESULT' + | 'DECLINED' + | 'DO_NOT_HONOR' + | 'DRIVER_NUMBER_INVALID' + | 'FORMAT_ERROR' + | 'INSUFFICIENT_FUNDING_SOURCE_BALANCE' + | 'INSUFFICIENT_FUNDS' + | 'LITHIC_SYSTEM_ERROR' + | 'LITHIC_SYSTEM_RATE_LIMIT' + | 'MALFORMED_ASA_RESPONSE' + | 'MERCHANT_INVALID' + | 'MERCHANT_LOCKED_CARD_ATTEMPTED_ELSEWHERE' + | 'MERCHANT_NOT_PERMITTED' + | 'OVER_REVERSAL_ATTEMPTED' + | 'PIN_BLOCKED' + | 'PROGRAM_CARD_SPEND_LIMIT_EXCEEDED' + | 'PROGRAM_SUSPENDED' + | 'PROGRAM_USAGE_RESTRICTION' + | 'REVERSAL_UNMATCHED' + | 'SECURITY_VIOLATION' + | 'SINGLE_USE_CARD_REATTEMPTED' + | 'SUSPECTED_FRAUD' + | 'TRANSACTION_INVALID' + | 'TRANSACTION_NOT_PERMITTED_TO_ACQUIRER_OR_TERMINAL' + | 'TRANSACTION_NOT_PERMITTED_TO_ISSUER_OR_CARDHOLDER' + | 'TRANSACTION_PREVIOUSLY_COMPLETED' + | 'UNAUTHORIZED_MERCHANT' + | 'VEHICLE_NUMBER_INVALID' + | 'CARDHOLDER_CHALLENGED' + | 'CARDHOLDER_CHALLENGE_FAILED'; + + type: 'DECLINE'; + + /** + * Optional explanation for why this action was taken + */ + explanation?: string; + } + + export interface ChallengeActionAuthorization { + type: 'CHALLENGE'; /** * Optional explanation for why this action was taken @@ -1252,7 +1613,7 @@ export namespace V2ListResultsResponse { /** * Actions returned by the rule evaluation */ - actions: Array; + actions: Array; /** * The Auth Rule token @@ -1286,7 +1647,7 @@ export namespace V2ListResultsResponse { } export namespace TokenizationResult { - export interface DeclineAction { + export interface DeclineActionTokenization { /** * Decline the tokenization request */ @@ -1358,7 +1719,7 @@ export namespace V2ListResultsResponse { /** * Actions returned by the rule evaluation */ - actions: Array; + actions: Array; /** * The Auth Rule token @@ -1392,7 +1753,7 @@ export namespace V2ListResultsResponse { } export namespace ACHResult { - export interface ApproveAction { + export interface ApproveActionACH { /** * Approve the ACH transaction */ @@ -1619,7 +1980,7 @@ export namespace V2RetrieveReportResponse { /** * Detailed statistics for the current version of the rule. */ - current_version_statistics: V2API.RuleStats | null; + current_version_statistics: V2API.ReportStats | null; /** * The date (UTC) for which the statistics are reported. @@ -1629,7 +1990,7 @@ export namespace V2RetrieveReportResponse { /** * Detailed statistics for the draft version of the rule. */ - draft_version_statistics: V2API.RuleStats | null; + draft_version_statistics: V2API.ReportStats | null; } } @@ -1918,6 +2279,18 @@ export interface V2ListResultsParams extends CursorPageParams { */ auth_rule_token?: string; + /** + * Date string in RFC 3339 format. Only events evaluated after the specified time + * will be included. UTC time zone. + */ + begin?: string; + + /** + * Date string in RFC 3339 format. Only events evaluated before the specified time + * will be included. UTC time zone. + */ + end?: string; + /** * Filter by event token */ @@ -1954,6 +2327,7 @@ export declare namespace V2 { export { type AuthRule as AuthRule, type AuthRuleCondition as AuthRuleCondition, + type BacktestStats as BacktestStats, type Conditional3DSActionParameters as Conditional3DSActionParameters, type ConditionalACHActionParameters as ConditionalACHActionParameters, type ConditionalAttribute as ConditionalAttribute, @@ -1964,7 +2338,7 @@ export declare namespace V2 { type ConditionalValue as ConditionalValue, type EventStream as EventStream, type MerchantLockParameters as MerchantLockParameters, - type RuleStats as RuleStats, + type ReportStats as ReportStats, type VelocityLimitParams as VelocityLimitParams, type VelocityLimitPeriod as VelocityLimitPeriod, type V2ListResultsResponse as V2ListResultsResponse, diff --git a/src/resources/payments.ts b/src/resources/payments.ts index 1fd9cea9..36f60559 100644 --- a/src/resources/payments.ts +++ b/src/resources/payments.ts @@ -606,6 +606,11 @@ export interface PaymentCreateParams { */ token?: string; + /** + * Optional hold to settle when this payment is initiated. + */ + hold?: PaymentCreateParams.Hold; + memo?: string; user_defined_id?: string; @@ -622,6 +627,16 @@ export namespace PaymentCreateParams { addenda?: string | null; } + + /** + * Optional hold to settle when this payment is initiated. + */ + export interface Hold { + /** + * Token of the hold to settle when this payment is initiated. + */ + token: string; + } } export interface PaymentListParams extends CursorPageParams { diff --git a/src/resources/webhooks.ts b/src/resources/webhooks.ts index 916dad08..e92629db 100644 --- a/src/resources/webhooks.ts +++ b/src/resources/webhooks.ts @@ -175,11 +175,6 @@ export namespace AccountHolderUpdatedWebhookEvent { * Original request to update the account holder. */ export interface UpdateRequest { - /** - * @deprecated Deprecated. - */ - beneficial_owner_entities?: Array; - /** * You must submit a list of all direct and indirect individuals with 25% or more * ownership in the company. A maximum of 4 beneficial owners can be submitted. If @@ -2501,11 +2496,6 @@ export namespace ParsedWebhookEvent { * Original request to update the account holder. */ export interface UpdateRequest { - /** - * @deprecated Deprecated. - */ - beneficial_owner_entities?: Array; - /** * You must submit a list of all direct and indirect individuals with 25% or more * ownership in the company. A maximum of 4 beneficial owners can be submitted. If diff --git a/src/version.ts b/src/version.ts index bfde34bc..63a530b5 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.130.0'; // x-release-please-version +export const VERSION = '0.131.0'; // x-release-please-version diff --git a/tests/api-resources/account-holders/account-holders.test.ts b/tests/api-resources/account-holders/account-holders.test.ts index 4429f670..490692da 100644 --- a/tests/api-resources/account-holders/account-holders.test.ts +++ b/tests/api-resources/account-holders/account-holders.test.ts @@ -119,23 +119,6 @@ describe('resource accountHolders', () => { nature_of_business: 'Software company selling solutions to the restaurant industry', tos_timestamp: '2018-05-29T21:16:05Z', workflow: 'KYB_BASIC', - beneficial_owner_entities: [ - { - address: { - address1: '123 Old Forest Way', - city: 'Omaha', - country: 'USA', - postal_code: '68022', - state: 'NE', - address2: 'address2', - }, - government_id: '114-123-1513', - legal_business_name: 'Acme, Inc.', - phone_numbers: ['+15555555555'], - dba_business_name: 'dba_business_name', - parent_company: 'parent_company', - }, - ], external_id: 'external_id', kyb_passed_timestamp: '2018-05-29T21:16:05Z', naics_code: '541512', diff --git a/tests/api-resources/auth-rules/v2/v2.test.ts b/tests/api-resources/auth-rules/v2/v2.test.ts index 7fa93ea9..488f6402 100644 --- a/tests/api-resources/auth-rules/v2/v2.test.ts +++ b/tests/api-resources/auth-rules/v2/v2.test.ts @@ -141,6 +141,8 @@ describe('resource v2', () => { client.authRules.v2.listResults( { auth_rule_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + begin: '2019-12-27T18:11:19.117Z', + end: '2019-12-27T18:11:19.117Z', ending_before: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', event_token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', has_actions: true, diff --git a/tests/api-resources/payments.test.ts b/tests/api-resources/payments.test.ts index 617dd768..d42b8cb6 100644 --- a/tests/api-resources/payments.test.ts +++ b/tests/api-resources/payments.test.ts @@ -39,6 +39,7 @@ describe('resource payments', () => { }, type: 'COLLECTION', token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + hold: { token: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' }, memo: 'memo', user_defined_id: 'user_defined_id', }); diff --git a/tests/api-resources/webhooks.test.ts b/tests/api-resources/webhooks.test.ts index 173c5bd1..728450b3 100644 --- a/tests/api-resources/webhooks.test.ts +++ b/tests/api-resources/webhooks.test.ts @@ -237,20 +237,27 @@ describe('resource webhooks', () => { }); describe('parse', () => { - it('should unwrap and validate typed webhook event', () => { - const secret = 'whsec_c2VjcmV0Cg=='; - const payload = - '{"event_type":"account_holder.created","token":"00000000-0000-0000-0000-000000000001","account_token":"00000000-0000-0000-0000-000000000001","created":"2019-12-27T18:11:19.117Z","required_documents":[{"entity_token":"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e","status_reasons":["string"],"valid_documents":["string"]}],"status":"ACCEPTED","status_reason":["string"]}'; + const secret = 'whsec_c2VjcmV0Cg=='; + const payload = + '{"event_type":"account_holder.created","token":"00000000-0000-0000-0000-000000000001","account_token":"00000000-0000-0000-0000-000000000001","created":"2019-12-27T18:11:19.117Z","required_documents":[{"entity_token":"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e","status_reasons":["string"],"valid_documents":["string"]}],"status":"ACCEPTED","status_reason":["string"]}'; + + function makeHeaders() { const msgID = '1'; const timestamp = new Date(); const wh = new Webhook(secret); const signature = wh.sign(msgID, timestamp, payload); - const headers: Record = { - 'webhook-signature': signature, - 'webhook-id': msgID, - 'webhook-timestamp': String(Math.floor(timestamp.getTime() / 1000)), + return { + wh, + headers: { + 'webhook-signature': signature, + 'webhook-id': msgID, + 'webhook-timestamp': String(Math.floor(timestamp.getTime() / 1000)), + } as Record, }; + } + it('should unwrap and validate typed webhook event', () => { + const { headers } = makeHeaders(); const event = lithic.webhooks.parse(payload, { headers, secret }); expect(event).toBeDefined(); if ('event_type' in event) { @@ -258,24 +265,44 @@ describe('resource webhooks', () => { } }); - it('should throw for wrong secret', () => { - const secret = 'whsec_c2VjcmV0Cg=='; - const payload = - '{"event_type":"account_holder.created","token":"00000000-0000-0000-0000-000000000001","account_token":"00000000-0000-0000-0000-000000000001","created":"2019-12-27T18:11:19.117Z","required_documents":[{"entity_token":"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e","status_reasons":["string"],"valid_documents":["string"]}],"status":"ACCEPTED","status_reason":["string"]}'; - const msgID = '1'; - const timestamp = new Date(); - const wh = new Webhook(secret); - const signature = wh.sign(msgID, timestamp, payload); - const headers: Record = { - 'webhook-signature': signature, - 'webhook-id': msgID, - 'webhook-timestamp': String(Math.floor(timestamp.getTime() / 1000)), - }; + it('should work with withOptions webhookSecret', () => { + const { headers } = makeHeaders(); - expect(() => { - const wrongSecret = 'whsec_' + Buffer.from('wrong_secret').toString('base64'); - lithic.webhooks.parse(payload, { headers, secret: wrongSecret }); - }).toThrow('No matching signature found'); + // secret via withOptions + lithic.withOptions({ webhookSecret: secret }).webhooks.parse(payload, { headers }); + + // per-call secret overrides withOptions + lithic + .withOptions({ webhookSecret: 'whsec_aaaaaaaaaa==' }) + .webhooks.parse(payload, { headers, secret }); + }); + + it.each([ + { + name: 'wrong secret', + tweakHeaders: (h: Record) => h, + overrideSecret: 'whsec_' + Buffer.from('wrong_secret').toString('base64'), + error: 'No matching signature found', + }, + { + name: 'bad signature from different payload', + tweakHeaders: (h: Record, wh: Webhook) => ({ + ...h, + 'webhook-signature': wh.sign('1', new Date(), 'some other payload'), + }), + error: 'No matching signature found', + }, + { + name: 'wrong message ID', + tweakHeaders: (h: Record) => ({ ...h, 'webhook-id': 'wrong' }), + error: 'No matching signature found', + }, + ])('should throw for $name', ({ tweakHeaders, overrideSecret, error }) => { + const { wh, headers } = makeHeaders(); + const tweaked = tweakHeaders(headers, wh); + expect(() => + lithic.webhooks.parse(payload, { headers: tweaked, secret: overrideSecret ?? secret }), + ).toThrow(error); }); });