From 3b1a67386c8698d3f35be51cec30ade057404520 Mon Sep 17 00:00:00 2001 From: danielzhao122 Date: Mon, 10 Nov 2025 14:29:07 -0500 Subject: [PATCH 1/2] fix: codec definition ticket: WP-6702 TICKET: WP-6702 --- modules/express/openapi-generator.rc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/express/openapi-generator.rc.js b/modules/express/openapi-generator.rc.js index 03d1f8cfa3..9d3a1cfb73 100644 --- a/modules/express/openapi-generator.rc.js +++ b/modules/express/openapi-generator.rc.js @@ -14,7 +14,7 @@ module.exports = (E) => { NonEmptyString: () => E.right({ type: 'string', minLength: 1 }), DateFromISOString: () => E.right({ type: 'string', format: 'date-time' }), BigIntFromString: () => E.right({ type: 'string' }), - BooleanFromString: () => E.right({ type: 'string', enum: ['true', 'false'] }), + BooleanFromString: () => E.right({ type: 'boolean' }), }, 'io-ts-bigint': { BigIntFromString: () => E.right({ type: 'string' }), From d1bfac533f526b3d1f022af2cd27ce88ba526f97 Mon Sep 17 00:00:00 2001 From: danielzhao122 Date: Tue, 11 Nov 2025 12:17:49 -0500 Subject: [PATCH 2/2] feat: add audit api specs to pr checks TICKET: WP-6702 --- .github/workflows/ci.yml | 83 ++++ modules/express/ruleset.yaml | 410 ++++++++++++++++++ .../src/typedRoutes/api/v2/generateWallet.ts | 2 +- .../test/unit/typedRoutes/generateWallet.ts | 2 +- 4 files changed, 495 insertions(+), 2 deletions(-) create mode 100644 modules/express/ruleset.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7f4219788..399ce165e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -368,3 +368,86 @@ jobs: git diff exit 1 fi + + audit-api-spec: + runs-on: ubuntu-latest + + steps: + - name: Checkout PR + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Setup Node.js 18 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: 22 + + - name: Restore lerna dependencies + id: lerna-cache + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: | + node_modules + modules/*/node_modules + key: ${{ runner.os }}-node18-${{ hashFiles('yarn.lock') }}-${{ hashFiles('tsconfig.packages.json') }}-${{ hashFiles('**/package.json') }} + + - name: Install Packages + if: steps.lerna-cache.outputs.cache-hit != 'true' + run: yarn install --with-frozen-lockfile --ignore-scripts + + - name: Build packages + env: + DISABLE_V8_COMPILE_CACHE: '1' + run: yarn run postinstall + + - name: Install OpenAPI Generator at root + run: yarn add -W @api-ts/openapi-generator@v5 + + - name: Download and install vacuum v0.18.1 + run: | + curl -L \ + --output vacuum.tar.gz \ + --silent \ + --show-error \ + --fail \ + https://github.com/daveshanley/vacuum/releases/download/v0.18.1/vacuum_0.18.1_linux_x86_64.tar.gz + tar -xzf vacuum.tar.gz + chmod u+x vacuum + sudo mv vacuum /usr/local/bin/ + vacuum version + + - name: Generate API spec + working-directory: modules/express + run: | + ../../node_modules/.bin/openapi-generator \ + --codec-file openapi-generator.rc.js \ + src/typedRoutes/api/index.ts \ + > api-generated.json + + - name: Audit with Vacuum + working-directory: modules/express + run: | + + vacuum report \ + --no-style \ + --stdout \ + --ruleset ruleset.yaml \ + api-generated.json > vacuum-report.json + + jq '.resultSet.results // []' vacuum-report.json > vacuum-results.json + + ERROR_COUNT=$(jq '[.[] | select(.ruleSeverity == "error")] | length' vacuum-results.json) + WARNING_COUNT=$(jq '[.[] | select(.ruleSeverity == "warn")] | length' vacuum-results.json) + + echo "Found $ERROR_COUNT error(s) and $WARNING_COUNT warning(s)" + + if [ "$ERROR_COUNT" -gt 0 ]; then + echo "API specification audit failed with $ERROR_COUNT error(s)" + echo "" + echo "Errors:" + jq -r '.[] | select(.ruleSeverity == "error") | " - [\(.ruleId)] \(.message) at \(.path)"' vacuum-results.json + exit 1 + else + echo "API specification audit passed!" + fi diff --git a/modules/express/ruleset.yaml b/modules/express/ruleset.yaml new file mode 100644 index 0000000000..e3cde7d955 --- /dev/null +++ b/modules/express/ruleset.yaml @@ -0,0 +1,410 @@ +description: Recommended rules for a high quality specification. +documentationUrl: https://quobix.com/vacuum/rulesets/recommended +rules: + duplicated-entry-in-enum: + category: + description: Schemas are how request bodies and response payloads are defined. They define the data going in and the data flowing out of an operation. These rules check for structural validity, checking types, checking required fields and validating correct use of structures. + id: schemas + name: Schemas + description: Enum values can't be the same. + formats: + - oas3 + - oas3_1 + - oas2 + given: $ + howToFix: Make each enum value unique. + id: duplicated-entry-in-enum + recommended: true + severity: error + then: + function: duplicatedEnum + type: validation + no-$ref-siblings: + category: + description: Schemas are how request bodies and response payloads are defined. They define the data going in and the data flowing out of an operation. These rules check for structural validity, checking types, checking required fields and validating correct use of structures. + id: schemas + name: Schemas + description: $ref values can't be next to other properties. + formats: + - oas3 + - oas3_1 + - oas2 + given: $ + howToFix: Remove all sibling nodes, including descriptions. + id: no-$ref-siblings + recommended: true + severity: error + then: + function: refSiblings + type: validation + no-ambiguous-paths: + category: + description: Operations are the core of the contract, they define paths and HTTP methods. These rules check operations have been well constructed, looks for operationId, parameter, schema and return types in depth. + id: operations + name: Operations + description: Paths must resolve unambiguously from one another. For example, /{id}/ambiguous and /ambiguous/{id} are the same thing. + formats: + - oas3 + - oas3_1 + - oas2 + given: $ + howToFix: Make the path, and the variables used, unique. Check the ordering of variables and the naming of path segments. + id: no-ambiguous-paths + recommended: true + resolved: true + severity: error + then: + function: noAmbiguousPaths + type: validation + no-eval-in-markdown: + category: + description: Validation rules make sure that certain characters or patterns have not been used that may cause issues when rendering in different types of applications. + id: validation + name: Validation + description: Markdown descriptions can't have `eval()` statements'. Malicious actors can use these to embed code in contracts, executing when a browser reads it. + formats: + - oas3 + - oas3_1 + - oas2 + given: $ + howToFix: Remove all references to 'eval()' from the description. + id: no-eval-in-markdown + recommended: true + resolved: true + severity: error + then: + function: noEvalDescription + functionOptions: + pattern: eval\( + type: validation + no-script-tags-in-markdown: + category: + description: Validation rules make sure that certain characters or patterns have not been used that may cause issues when rendering in different types of applications. + id: validation + name: Validation + description: Markdown descriptions can't have `