From 8adc05a2f5c382ed4e35021d238127a7fbfce37d Mon Sep 17 00:00:00 2001 From: Pranish Nepal Date: Tue, 16 Jun 2026 10:28:33 -0400 Subject: [PATCH] feat: update master express openapi spec & ci job This commit updates the master express openapi spec and adds a ci job to check for drifts. Ticket: WAL-157 --- .github/workflows/pull_request.yaml | 29 ++ masterBitgoExpress.json | 507 +++++++++++++++++-------- package-lock.json | 41 +- package.json | 6 +- scripts/check-openapi-masterExpress.sh | 34 ++ 5 files changed, 436 insertions(+), 181 deletions(-) create mode 100644 scripts/check-openapi-masterExpress.sh diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index a9887da7..e0320338 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -18,6 +18,35 @@ jobs: secrets: fossa-api-key: ${{ secrets.FOSSA_API_KEY }} + check-openapi-drift: + name: Check OpenAPI spec drift + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22.1.0' + cache: 'npm' + + - name: Cache dependencies + uses: actions/cache@v5 + id: node-modules-cache + with: + path: '**/node_modules' + key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-modules- + + - name: Install dependencies + if: steps.node-modules-cache.outputs.cache-hit != 'true' + run: npm ci + + - name: Check OpenAPI spec drift + run: npm run check:openapi:masterExpress + check-dependency-changes: name: Check for dependency changes runs-on: ubuntu-latest diff --git a/masterBitgoExpress.json b/masterBitgoExpress.json index 6399bae2..a0245e55 100644 --- a/masterBitgoExpress.json +++ b/masterBitgoExpress.json @@ -2,14 +2,64 @@ "openapi": "3.0.3", "info": { "title": "@bitgo/master-bitgo-express", - "version": "2.0.0", + "version": "0.0.0-semantically-released", "description": "Advanced Wallets - On-Premises Key Management with BitGo Express" }, "paths": { + "/advancedwallet/ping": { + "post": { + "summary": "Advanced Wallets - Ping", + "description": "Test your connection to the Master Bitgo Express (MBE) server.", + "operationId": "advancedwallet.mbe.ping", + "tags": [ + "Advanced Wallets" + ], + "parameters": [], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PingResponseType" + } + } + } + } + } + } + }, + "/advancedwallet/version": { + "get": { + "summary": "Advanced Wallets - Check Version", + "description": "Check your version of the Master Bitgo Express (MBE) server.", + "operationId": "advancedwallet.mbe.version", + "tags": [ + "Advanced Wallets" + ], + "parameters": [], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionResponseType" + } + } + } + } + } + } + }, "/api/v1/{coin}/advancedwallet/{walletId}/accelerate": { "post": { - "summary": "Accelerate unconfirmed transactions on UTXO-based blockchains.", - "description": "Supports Child-Pays-For-Parent (CPFP) and Replace-By-Fee (RBF) acceleration methods.", + "summary": "Advanced Wallets - Accelerate Transaction", + "description": "Send a new transaction to accelerate the targeted unconfirmed transaction either by using Child-Pays-For-Parent (CPFP) or Replace-By-Fee (RBF).\n\nRetrieves the private key from key provider using the provided public key, then signs and broadcasts the transaction.\n\nUse this endpoint only with advanced wallets. For other wallet types, use [Accelerate Transaction](https://developers.bitgo.com/reference/expresswalletacceleratetx).", + "operationId": "advancedwallet.accelerate.tx", + "tags": [ + "Advanced Wallets" + ], "parameters": [ { "name": "walletId", @@ -33,7 +83,6 @@ "application/json": { "schema": { "type": "object", - "description": "Request type for the transaction acceleration endpoint. Used to accelerate unconfirmed transactions on UTXO-based blockchains using CPFP or RBF.", "properties": { "pubkey": { "type": "string", @@ -99,28 +148,16 @@ "content": { "application/json": { "schema": { - "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/AccelerateResponseCodec" + } + ], "description": "Successful acceleration response.", "example": { "txid": "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234", "tx": "01000000000101edd7a5d948a6c79f273ce686a6a8f2e96ed8c2583b5e77b866aa2a1b3426fbed0100000000ffffffff02102700000000000017a914192f23283c2a9e6c5d11562db0eb5d4eb47f460287b9bc2c000000000017a9145c139b242ab3701f321d2399d3a11b028b3b361e870247304402206ac9477fece38d96688c6c3719cb27396c0563ead0567457e7e884b406b6da8802201992d1cfa1b55a67ce8acb482e9957812487d2555f5f54fb0286ecd3095d78e4012103c92564575197c4d6e3d9792280e7548b3ba52a432101c62de2186c4e2fa7fc580000000000" - }, - "properties": { - "txid": { - "type": "string", - "description": "The transaction ID (hash) of the acceleration transaction. This can be used to track the transaction on a block explorer.", - "example": "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234" - }, - "tx": { - "type": "string", - "description": "The full signed transaction in hexadecimal format. This transaction can be broadcast to the network.", - "example": "01000000000101edd7a5d948a6c79f273ce686a6a8f2e96ed8c2583b5e77b866aa2a1b3426fbed0100000000ffffffff02102700000000000017a914192f23283c2a9e6c5d11562db0eb5d4eb47f460287b9bc2c000000000017a9145c139b242ab3701f321d2399d3a11b028b3b361e870247304402206ac9477fece38d96688c6c3719cb27396c0563ead0567457e7e884b406b6da8802201992d1cfa1b55a67ce8acb482e9957812487d2555f5f54fb0286ecd3095d78e4012103c92564575197c4d6e3d9792280e7548b3ba52a432101c62de2186c4e2fa7fc580000000000" - } - }, - "required": [ - "txid", - "tx" - ] + } } } } @@ -190,8 +227,12 @@ }, "/api/v1/{coin}/advancedwallet/{walletId}/consolidate": { "post": { - "summary": "Build, sign, and send a consolidation transaction for an account-based asset all in 1 call.", - "description": "For account-based assets, consolidating the balances in the receive addresses to the base address maximizes the spendable balance of a wallet.", + "summary": "Advanced Wallets - Consolidate Account", + "description": "Build, sign, and send a consolidation transaction, all in one call. For account-based assets, consolidating the balances in the receive addresses to the base address maximizes the spendable balance of a wallet.\n\nRetrieves the private key from key provider using the provided public key or common keychain, then signs and broadcasts the transaction.\n\nUse this endpoint only with advanced wallets. For other wallet types, use [Consolidate account (simple)](https://developers.bitgo.com/reference/expresswalletconsolidateaccount).", + "operationId": "advancedwallet.consolidate", + "tags": [ + "Advanced Wallets" + ], "parameters": [ { "name": "walletId", @@ -329,8 +370,12 @@ }, "/api/v1/{coin}/advancedwallet/{walletId}/consolidateunspents": { "post": { - "summary": "Build and send a transaction to consolidate unspents in a wallet.", - "description": "Consolidating unspents is only for UTXO-based assets.", + "summary": "Advanced Wallets - Consolidate Unspents", + "description": "Builds, signs, and sends a transaction to consolidate unspents all in 1 call. Consolidating unspents is only for UTXO-based assets.\n\nRetrieves the private key from key provider using the provided public key, then signs and broadcasts the transaction.\n\nUse this endpoint only with advanced wallets. For other wallet types, use [Consolidate unspents (simple)](https://developers.bitgo.com/reference/expresswalletconsolidateunspents).", + "operationId": "advancedwallet.consolidate.unspents", + "tags": [ + "Advanced Wallets" + ], "parameters": [ { "name": "walletId", @@ -448,19 +493,7 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "tx": { - "type": "string" - }, - "txid": { - "type": "string" - } - }, - "required": [ - "tx", - "txid" - ] + "$ref": "#/components/schemas/ConsolidateUnspentsResponseCodec" } } } @@ -530,6 +563,12 @@ }, "/api/v1/{coin}/advancedwallet/{walletId}/sendMany": { "post": { + "summary": "Advanced Wallets - Send to Many", + "description": "Send coins or tokens to one or more recipients. You can use this endpoint to schedule outgoing transactions in bulk, lowering your aggregate amount of blockchain fees.\n\nRetrieves the private key from key provider using the provided public key, then signs and broadcasts the transaction.\n\nWorks with both multisignature and MPC wallets.\n\nWorks with most BitGo-supported assets, but currently unavailable for: ALGO, ARBETH, AVAXC, CELO, CELO:CUSD, CSPR, DOT, EOS, HTETH:BGERCH, NEAR, OPETH, STX, TON, TRX, TRX:USDC, XLM, XRP, XTZ\n\nUse this endpoint only with advanced wallets. For other wallet types, use [Send to many](https://developers.bitgo.com/reference/expresswalletsendmany).", + "operationId": "advancedwallet.sendmany", + "tags": [ + "Advanced Wallets" + ], "parameters": [ { "name": "walletId", @@ -573,7 +612,7 @@ "transfertoken", "trustline" ], - "description": "Required for transactions from MPC wallets." + "description": "Required for transactions from MPC wallets. Defaults to 'transfer' for TSS wallets if not provided." }, "recipients": { "type": "array", @@ -823,8 +862,12 @@ }, "/api/v1/{coin}/advancedwallet/{walletId}/txrequest/{txRequestId}/signAndSend": { "post": { - "summary": "Sign a TxRequest and Broadcast it (MPC wallets only)", - "description": "This is usually needed after resolving a pending approval for a MPC wallet", + "summary": "Advanced Wallets - Sign and Send MPC Transaction", + "description": "Sign and send a MPC transaction.\n\nRetrieves the private key from key provider using the provided common keychain, then signs and broadcasts the transaction.\n\nUse this endpoint only with advanced wallets. For other wallet types, use [Sign MPC transaction](https://developers.bitgo.com/reference/expresswalletsigntxtss).", + "operationId": "advancedwallet.sign.tx.tss", + "tags": [ + "Advanced Wallets" + ], "parameters": [ { "name": "walletId", @@ -952,8 +995,12 @@ }, "/api/v1/{coin}/advancedwallet/generate": { "post": { - "summary": "Generates a new advanced wallet.", - "description": "The wallet creation process involves several steps that happen automatically:\n1. User Keychain Creation: Creates the user keychain in the advanced wallet manager and encrypts it with the respective key provider.\n2. Backup Keychain Creation: Creates the backup keychain in the advanced wallet manager and encrypts it with the respective key provider.\n3. Keychain Upload: Uploads the user/backup public keys to BitGo.\n4. BitGo Key Creation: Creates the BitGo key on the BitGo service.\n5. Wallet Creation: Creates the wallet on BitGo with the 3 keys.", + "summary": "Advanced Wallets - Generate Wallet", + "description": "Create a new advanced wallet. Calling this endpoint does the following:\n1. Generates user keychain in isolated AWM, then sends to key provider (encrypts private key, stores public key mapping).\n2. Generates backup keychain in isolated AWM, then sends to key provider (encrypts private key, stores public key mapping).\n3. Uploads the user and backup public keys to BitGo.\n4. Creates the BitGo key on the BitGo service.\n5. Creates the wallet on BitGo with the 3 keys.", + "operationId": "advancedwallet.generate", + "tags": [ + "Advanced Wallets" + ], "parameters": [ { "name": "coin", @@ -1006,6 +1053,12 @@ "example": 1, "minimum": 0, "maximum": 3 + }, + "evmKeyRingReferenceWalletId": { + "type": "string", + "description": "Reference wallet ID for EVM keyring wallets", + "example": "59cd72485007a239fb00282ed480da1f", + "pattern": "^[0-9a-f]{32}$" } }, "required": [ @@ -1023,31 +1076,17 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "wallet": { - "$ref": "#/components/schemas/WalletType" - }, - "userKeychain": { - "$ref": "#/components/schemas/UserKeychainType" - }, - "backupKeychain": { - "$ref": "#/components/schemas/UserKeychainType" - }, - "bitgoKeychain": { - "$ref": "#/components/schemas/BitgoKeychainType" - }, - "responseType": { - "type": "string" - } - }, - "required": [ - "wallet", - "userKeychain", - "backupKeychain", - "bitgoKeychain", - "responseType" - ] + "$ref": "#/components/schemas/GenerateWalletResponseCodec" + } + } + } + }, + "202": { + "description": "Accepted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AsyncJobResponseCodec" } } } @@ -1117,8 +1156,12 @@ }, "/api/v1/{coin}/advancedwallet/recovery": { "post": { - "summary": "Recover funds from an existing wallet using user and backup keys.", - "description": "This endpoint allows for both standard multisig and TSS wallet recovery.", + "summary": "Advanced Wallets - Recover Assets", + "description": "Recover assets from an advanced wallet with a balance only in the base address. Works for both multisignature and MPC recoveries.\n\nRetrieves the private keys from key provider using the provided public keys or common keychain, then signs and returns the broadcastable transaction hex.\n\nNote: This endpoint only works when AWM and MBE are running in recovery mode.\n\nTo recover assets from an advanced wallet with balances in multiple receive addresses, use [Advanced Wallets - Consolidate and Recover Assets](https://developers.bitgo.com/reference/advancedwalletconsolidaterecovery).\n\nUse this endpoint only with advanced wallets. For other wallet types, use the [Wallet Recovery Wizard](https://developers.bitgo.com/docs/wallets-recover#/).", + "operationId": "advancedwallet.recovery", + "tags": [ + "Advanced Wallets" + ], "parameters": [ { "name": "coin", @@ -1134,7 +1177,7 @@ "application/json": { "schema": { "type": "object", - "description": "Request type for the wallet recovery endpoint. Used to recover funds from both standard multisig and TSS wallets.", + "description": "Request type for the wallet recovery endpoint. Used to recover funds from both standard multisig and TSS wallets. Recover funds from an advanced wallet by building a transaction with user and backup keys.", "properties": { "isTssRecovery": { "type": "boolean", @@ -1389,20 +1432,15 @@ "content": { "application/json": { "schema": { - "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/RecoveryWalletResponseCodec" + } + ], "description": "Successful recovery response.", "example": { "txHex": "01000000000101edd7a5d948a6c79f273ce686a6a8f2e96ed8c2583b5e77b866aa2a1b3426fbed0100000000ffffffff02102700000000000017a914192f23283c2a9e6c5d11562db0eb5d4eb47f460287b9bc2c000000000017a9145c139b242ab3701f321d2399d3a11b028b3b361e870247304402206ac9477fece38d96688c6c3719cb27396c0563ead0567457e7e884b406b6da8802201992d1cfa1b55a67ce8acb482e9957812487d2555f5f54fb0286ecd3095d78e4012103c92564575197c4d6e3d9792280e7548b3ba52a432101c62de2186c4e2fa7fc580000000000" - }, - "properties": { - "txHex": { - "type": "string", - "description": "The full signed transaction in hexadecimal format. This transaction can be broadcast to the network to complete the recovery." - } - }, - "required": [ - "txHex" - ] + } } } } @@ -1472,8 +1510,12 @@ }, "/api/v1/{coin}/advancedwallet/recoveryconsolidations": { "post": { - "summary": "Consolidate funds from multiple addresses in a wallet and sign with user & backup keys in a recovery situation.", - "description": "Used for both standard multisig wallets and TSS wallets to consolidate funds from various addresses.", + "summary": "Advanced Wallets - Consolidate and Recover Assets", + "description": "Recover assets from an advanced wallet with a balance in multiple receive addresses. Build, sign, and send a consolidation and recovery, all in one call. Sign using your user and backup keys. Works for both multisignature and MPC recoveries.\n\nRetrieves the private keys from key provider using the provided public keys or common keychain, then signs and returns the broadcastable transaction hex.\n\nNote: This endpoint only works when AWM and MBE are running in recovery mode.\n\nTo recover assets from an advanced wallet with a balance only in the base address, use [Advanced Wallets - Recover Assets](https://developers.bitgo.com/reference/advancedwalletrecovery).\n\nUse this endpoint only with advanced wallets. For other wallet types, use the [Wallet Recovery Wizard](https://developers.bitgo.com/docs/wallets-recover#/).", + "operationId": "advancedwallet.consolidate.recovery", + "tags": [ + "Advanced Wallets" + ], "parameters": [ { "name": "coin", @@ -1647,45 +1689,70 @@ } } }, - "/ping": { - "post": { - "parameters": [], + "/api/v1/advancedwallet/job/{jobId}": { + "get": { + "summary": "Fetch job status for a given job ID.", + "operationId": "advancedwallet.getJob", + "tags": [ + "Advanced Wallets" + ], + "parameters": [ + { + "name": "jobId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PingResponseType" + "$ref": "#/components/schemas/MbeJobPollResponseCodec" } } } - } - } - } - }, - "/ping/advancedWalletManager": { - "post": { - "parameters": [], - "responses": { - "200": { - "description": "OK", + }, + "400": { + "description": "Bad Request", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "status": { - "type": "string" - }, - "awmResponse": { - "$ref": "#/components/schemas/PingResponseType" - } - }, - "required": [ - "status", - "awmResponse" - ] + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "422": { + "description": "Unprocessable Entity", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" } } } @@ -1695,36 +1762,17 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "error": { - "type": "string" - }, - "details": { - "type": "string" - } - }, - "required": [ - "error", - "details" - ] + "$ref": "#/components/schemas/ErrorResponse" } } } - } - } - } - }, - "/version": { - "get": { - "parameters": [], - "responses": { - "200": { - "description": "OK", + }, + "501": { + "description": "Not Implemented", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VersionResponseType" + "$ref": "#/components/schemas/ErrorResponse" } } } @@ -1732,8 +1780,14 @@ } } }, - "/version/advancedWalletManager": { - "get": { + "/ping/advancedWalletManager": { + "post": { + "summary": "Advanced Wallets - Ping Advanced Wallet Manager", + "description": "Test your connection between the Advanced Wallet Manager (AWM) and the Master Bitgo Express (MBE) servers.", + "operationId": "advancedwallet.mbe.awm.ping", + "tags": [ + "Advanced Wallets" + ], "parameters": [], "responses": { "200": { @@ -1741,7 +1795,19 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VersionResponseType" + "type": "object", + "properties": { + "status": { + "type": "string" + }, + "awmResponse": { + "$ref": "#/components/schemas/PingResponseType" + } + }, + "required": [ + "status", + "awmResponse" + ] } } } @@ -1774,22 +1840,6 @@ }, "components": { "schemas": { - "VersionResponseType": { - "title": "VersionResponseType", - "type": "object", - "properties": { - "version": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "version", - "name" - ] - }, "PingResponseType": { "title": "PingResponseType", "type": "object", @@ -1824,6 +1874,137 @@ "details" ] }, + "MbeJobPollResponseCodec": { + "title": "MbeJobPollResponseCodec", + "type": "object", + "properties": { + "jobId": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/MbeJobPollStatusCodec" + }, + "result": { + "type": "object", + "additionalProperties": {} + }, + "error": { + "type": "string" + }, + "round": { + "type": "number" + }, + "totalRounds": { + "type": "number" + } + }, + "required": [ + "jobId", + "status" + ] + }, + "MbeJobPollStatusCodec": { + "title": "MbeJobPollStatusCodec", + "type": "string", + "enum": [ + "awaiting_client", + "awaiting_bitgo", + "complete", + "failed" + ] + }, + "ConsolidateUnspentsResponseCodec": { + "title": "ConsolidateUnspentsResponseCodec", + "type": "object", + "properties": { + "tx": { + "type": "string" + }, + "txid": { + "type": "string" + } + }, + "required": [ + "tx", + "txid" + ] + }, + "AccelerateResponseCodec": { + "title": "AccelerateResponseCodec", + "type": "object", + "properties": { + "txid": { + "type": "string" + }, + "tx": { + "type": "string" + } + }, + "required": [ + "txid", + "tx" + ] + }, + "RecoveryWalletResponseCodec": { + "title": "RecoveryWalletResponseCodec", + "type": "object", + "description": "Response type for the wallet recovery endpoint. Returns the signed recovery transaction that can be broadcast to the network", + "properties": { + "txHex": { + "type": "string" + } + }, + "required": [ + "txHex" + ] + }, + "AsyncJobResponseCodec": { + "title": "AsyncJobResponseCodec", + "type": "object", + "properties": { + "jobId": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "pending" + ] + } + }, + "required": [ + "jobId", + "status" + ] + }, + "GenerateWalletResponseCodec": { + "title": "GenerateWalletResponseCodec", + "type": "object", + "properties": { + "wallet": { + "$ref": "#/components/schemas/WalletType" + }, + "userKeychain": { + "$ref": "#/components/schemas/UserKeychainType" + }, + "backupKeychain": { + "$ref": "#/components/schemas/UserKeychainType" + }, + "bitgoKeychain": { + "$ref": "#/components/schemas/BitgoKeychainType" + }, + "responseType": { + "type": "string" + } + }, + "required": [ + "wallet", + "userKeychain", + "backupKeychain", + "bitgoKeychain", + "responseType" + ] + }, "WalletType": { "title": "WalletType", "type": "object", @@ -2235,6 +2416,22 @@ "isTrust", "hsmType" ] + }, + "VersionResponseType": { + "title": "VersionResponseType", + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "version", + "name" + ] } } } diff --git a/package-lock.json b/package-lock.json index ebcb1ffb..13d5d425 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,6 @@ "version": "0.0.0-semantically-released", "dependencies": { "@api-ts/io-ts-http": "^3.2.1", - "@api-ts/openapi-generator": "^6.0.1", "@api-ts/response": "^2.1.0", "@api-ts/superagent-wrapper": "^1.3.3", "@api-ts/typed-express-router": "2.0.0", @@ -21117,9 +21116,10 @@ "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { "version": "1.1.1", @@ -21135,12 +21135,6 @@ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz", - "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==", - "license": "BSD-3-Clause" - }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", @@ -31430,15 +31424,16 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -32233,9 +32228,10 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -41461,19 +41457,18 @@ "dev": true }, "node_modules/protobufjs": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.0.tgz", - "integrity": "sha512-LtESOsMPTZgyYtwxhvdgdjGL0HmXEaRA/hVD6sol4zA60hVXXXP/SGmxnqDbgGE8gy7pYex7cym+5vYPcmaXBQ==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.4.tgz", + "integrity": "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", - "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", diff --git a/package.json b/package.json index c31fae82..ef88a88b 100644 --- a/package.json +++ b/package.json @@ -20,13 +20,13 @@ "test:integration": "NODE_ENV=test TS_NODE_PROJECT=tsconfig.integ.json mocha --config .mocharc.integ.js", "docker:test:integration": "bash scripts/run-integration-tests.sh", "generate:openapi:masterExpress": "npx @api-ts/openapi-generator --name @bitgo/master-bitgo-express ./src/masterBitgoExpress/routers/index.ts > masterBitgoExpress.json", + "check:openapi:masterExpress": "bash scripts/check-openapi-masterExpress.sh", "container:build:master-bitgo-express": "podman build --build-arg PORT=3081 -t master-bitgo-express .", "container:build:advanced-wallet-manager": "podman build --build-arg PORT=3080 -t advanced-wallet-manager .", "bump-versions": "ts-node scripts/bump-version.ts" }, "dependencies": { "@api-ts/io-ts-http": "^3.2.1", - "@api-ts/openapi-generator": "^6.0.1", "@api-ts/response": "^2.1.0", "@api-ts/superagent-wrapper": "^1.3.3", "@api-ts/typed-express-router": "2.0.0", @@ -126,7 +126,7 @@ "@bitgo-beta/statics": "15.1.1-beta.1782", "elliptic": "^6.6.1", "expo": "^48.0.0", - "form-data": "^4.0.4", + "form-data": "^4.0.6", "axios": "^1.13.5", "node-fetch": "^2.6.7", "secp256k1": "^5.0.1", @@ -151,7 +151,7 @@ "xml2js": "^0.5.0", "glob": "^11.1.0", "@xmldom/xmldom": "^0.9.10", - "protobufjs": "^7.5.5", + "protobufjs": "^7.6.1", "lodash": "^4.18.0" }, "devDependencies": { diff --git a/scripts/check-openapi-masterExpress.sh b/scripts/check-openapi-masterExpress.sh new file mode 100644 index 00000000..8378b3c7 --- /dev/null +++ b/scripts/check-openapi-masterExpress.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +set -euo pipefail + +SPEC_FILE="masterBitgoExpress.json" +BEFORE="$(mktemp)" +trap 'rm -f "$BEFORE"' EXIT + +if [ ! -f "$SPEC_FILE" ]; then + echo "Error: $SPEC_FILE not found" + exit 1 +fi + +cp "$SPEC_FILE" "$BEFORE" +npm run generate:openapi:masterExpress + +if diff -q "$BEFORE" "$SPEC_FILE" > /dev/null; then + echo "✅ OpenAPI spec is up to date." + exit 0 +fi + +echo "::error::$SPEC_FILE is out of sync with route code." +diff "$BEFORE" "$SPEC_FILE" || true +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "🚨 OpenAPI spec drift detected!" +echo "" +echo " ➤ To fix, run:" +echo "" +echo " npm run generate:openapi:masterExpress" +echo " git add masterBitgoExpress.json && git commit" +echo "" +echo " ⚠️ Never hand-edit masterBitgoExpress.json directly." +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +exit 1