From 23baf62514c2948753ddd7a377bc7bd0852c8d17 Mon Sep 17 00:00:00 2001 From: Brad Anderson Date: Mon, 5 Oct 2026 14:36:16 -0400 Subject: [PATCH 1/4] chore(lint): lint test/ with ESLint Tests were excluded from ESLint because they sit outside tsconfig's include, so the typed parser couldn't load them. Add test/tsconfig.json so the project service finds them, drop the test/ ignore, and use jest.requireActual in the mock factory instead of a bare require. --- packages/react-native-quick-crypto/eslint.config.mjs | 8 ++++---- .../react-native-quick-crypto/test/jestMock.test.ts | 2 +- packages/react-native-quick-crypto/test/tsconfig.json | 10 ++++++++++ 3 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 packages/react-native-quick-crypto/test/tsconfig.json diff --git a/packages/react-native-quick-crypto/eslint.config.mjs b/packages/react-native-quick-crypto/eslint.config.mjs index 8e8e7af3..c5cd6419 100644 --- a/packages/react-native-quick-crypto/eslint.config.mjs +++ b/packages/react-native-quick-crypto/eslint.config.mjs @@ -66,11 +66,11 @@ export default [ // Ignore patterns { ignores: [ - '.prettierrc.js', - '*.config.*js', - '*.plugin.js', + '.prettierrc.js', + '*.config.*js', + '*.plugin.js', '**/lib/**', '**/build/**', - '**/test/**'], + ], }, ]; diff --git a/packages/react-native-quick-crypto/test/jestMock.test.ts b/packages/react-native-quick-crypto/test/jestMock.test.ts index 9261b1e6..47bb3b04 100644 --- a/packages/react-native-quick-crypto/test/jestMock.test.ts +++ b/packages/react-native-quick-crypto/test/jestMock.test.ts @@ -1,6 +1,6 @@ // `virtual` because the package can't resolve its own name inside this repo; // apps use the same call without it. -jest.mock('react-native-quick-crypto', () => require('../jest'), { +jest.mock('react-native-quick-crypto', () => jest.requireActual('../jest'), { virtual: true, }); diff --git a/packages/react-native-quick-crypto/test/tsconfig.json b/packages/react-native-quick-crypto/test/tsconfig.json new file mode 100644 index 00000000..6eac514c --- /dev/null +++ b/packages/react-native-quick-crypto/test/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "composite": false, + "rootDir": "..", + "noEmit": true, + "types": ["jest", "node"] + }, + "include": ["."] +} From 3c92c1b17bff95193a73ce78b45008907d678455 Mon Sep 17 00:00:00 2001 From: Brad Anderson Date: Mon, 5 Oct 2026 14:51:42 -0400 Subject: [PATCH 2/4] fix(subtle): accept algorithm names as strings in public methods WebCrypto takes an AlgorithmIdentifier (object or name string), and normalizeAlgorithm already handles strings at runtime, but the public signatures only allowed objects, so subtle.sign('HMAC', ...) failed to type-check. Widen them to | AnyAlgorithm, matching digest/importKey. --- .../react-native-quick-crypto/src/subtle.ts | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/react-native-quick-crypto/src/subtle.ts b/packages/react-native-quick-crypto/src/subtle.ts index 6415a8df..8302e5aa 100644 --- a/packages/react-native-quick-crypto/src/subtle.ts +++ b/packages/react-native-quick-crypto/src/subtle.ts @@ -3541,7 +3541,7 @@ export class Subtle { } async decrypt( - algorithm: EncryptDecryptParams, + algorithm: EncryptDecryptParams | AnyAlgorithm, key: CryptoKey, data: BufferLike, ): Promise { @@ -3577,7 +3577,7 @@ export class Subtle { } async deriveBits( - algorithm: SubtleAlgorithm, + algorithm: SubtleAlgorithm | AnyAlgorithm, baseKey: CryptoKey, length: number | null = null, ): Promise { @@ -3633,9 +3633,9 @@ export class Subtle { } async deriveKey( - algorithm: SubtleAlgorithm, + algorithm: SubtleAlgorithm | AnyAlgorithm, baseKey: CryptoKey, - derivedKeyAlgorithm: SubtleAlgorithm, + derivedKeyAlgorithm: SubtleAlgorithm | AnyAlgorithm, extractable: boolean, keyUsages: KeyUsage[], ): Promise { @@ -3723,7 +3723,7 @@ export class Subtle { } async encrypt( - algorithm: EncryptDecryptParams, + algorithm: EncryptDecryptParams | AnyAlgorithm, key: CryptoKey, data: BufferLike, ): Promise { @@ -3800,7 +3800,7 @@ export class Subtle { format: ImportFormat, key: CryptoKey, wrappingKey: CryptoKey, - wrapAlgorithm: EncryptDecryptParams, + wrapAlgorithm: EncryptDecryptParams | AnyAlgorithm, ): Promise { requireArgs(arguments.length, 4, 'wrapKey'); // Mirrors Node webcrypto.js:923-927: prefer the 'wrapKey' op (only @@ -3868,7 +3868,7 @@ export class Subtle { format: ImportFormat, wrappedKey: BufferLike, unwrappingKey: CryptoKey, - unwrapAlgorithm: EncryptDecryptParams, + unwrapAlgorithm: EncryptDecryptParams | AnyAlgorithm, unwrappedKeyAlgorithm: SubtleAlgorithm | AnyAlgorithm, extractable: boolean, keyUsages: KeyUsage[], @@ -3941,7 +3941,7 @@ export class Subtle { } async generateKey( - algorithm: SubtleAlgorithm, + algorithm: SubtleAlgorithm | AnyAlgorithm, extractable: boolean, keyUsages: KeyUsage[], ): Promise { @@ -4289,7 +4289,7 @@ export class Subtle { } async sign( - algorithm: SubtleAlgorithm, + algorithm: SubtleAlgorithm | AnyAlgorithm, key: CryptoKey, data: BufferLike, ): Promise { @@ -4302,7 +4302,7 @@ export class Subtle { } async verify( - algorithm: SubtleAlgorithm, + algorithm: SubtleAlgorithm | AnyAlgorithm, key: CryptoKey, signature: BufferLike, data: BufferLike, @@ -4317,7 +4317,7 @@ export class Subtle { } private _encapsulateCore( - algorithm: SubtleAlgorithm, + algorithm: SubtleAlgorithm | AnyAlgorithm, key: CryptoKey, ): EncapsulateResult { const normalizedAlgorithm = normalizeAlgorithm( @@ -4346,7 +4346,7 @@ export class Subtle { } private _decapsulateCore( - algorithm: SubtleAlgorithm, + algorithm: SubtleAlgorithm | AnyAlgorithm, key: CryptoKey, ciphertext: BufferLike, ): ArrayBuffer { @@ -4376,7 +4376,7 @@ export class Subtle { } async encapsulateBits( - algorithm: SubtleAlgorithm, + algorithm: SubtleAlgorithm | AnyAlgorithm, key: CryptoKey, ): Promise { requireArgs(arguments.length, 2, 'encapsulateBits'); @@ -4391,7 +4391,7 @@ export class Subtle { } async encapsulateKey( - algorithm: SubtleAlgorithm, + algorithm: SubtleAlgorithm | AnyAlgorithm, key: CryptoKey, sharedKeyAlgorithm: SubtleAlgorithm | AnyAlgorithm, extractable: boolean, @@ -4420,7 +4420,7 @@ export class Subtle { } async decapsulateBits( - algorithm: SubtleAlgorithm, + algorithm: SubtleAlgorithm | AnyAlgorithm, key: CryptoKey, ciphertext: BufferLike, ): Promise { @@ -4436,7 +4436,7 @@ export class Subtle { } async decapsulateKey( - algorithm: SubtleAlgorithm, + algorithm: SubtleAlgorithm | AnyAlgorithm, key: CryptoKey, ciphertext: BufferLike, sharedKeyAlgorithm: SubtleAlgorithm | AnyAlgorithm, From cb5bd81a877762daddddada34bf444625b448b5f Mon Sep 17 00:00:00 2001 From: Brad Anderson Date: Mon, 5 Oct 2026 15:46:26 -0400 Subject: [PATCH 3/4] ci: unblock bun audit and Android SDK setup - Ignore GHSA-vfj7-8cjw-p6xm (braces <=3.0.3, no patched release). Like the existing ignores, it only reaches the audit through metro via the react-native peer, not a consumer's runtime bundle. - Bump android-actions/setup-android to v4. v3 installs the 'tools' package, which Google no longer serves, so setup fails with "Failed to find package 'tools'" (android-actions/setup-android#538). --- .github/workflows/e2e-android-test.yml | 6 +++--- .github/workflows/validate-js.yml | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/e2e-android-test.yml b/.github/workflows/e2e-android-test.yml index b32e3361..35eb8d5a 100644 --- a/.github/workflows/e2e-android-test.yml +++ b/.github/workflows/e2e-android-test.yml @@ -80,7 +80,7 @@ jobs: sudo apt-get install -y libssl-dev pkg-config - name: Setup Android SDK - uses: android-actions/setup-android@v3 + uses: android-actions/setup-android@v4 - name: Install Dependencies run: bun install @@ -164,7 +164,7 @@ jobs: steps: - name: Setup Android SDK - uses: android-actions/setup-android@v3 + uses: android-actions/setup-android@v4 - name: Enable KVM run: | @@ -230,7 +230,7 @@ jobs: mkdir -p $HOME/.maestro/tests/ - name: Setup Android SDK - uses: android-actions/setup-android@v3 + uses: android-actions/setup-android@v4 - name: Restore node_modules cache uses: actions/cache/restore@v5 diff --git a/.github/workflows/validate-js.yml b/.github/workflows/validate-js.yml index c5645d3b..9753f2c3 100644 --- a/.github/workflows/validate-js.yml +++ b/.github/workflows/validate-js.yml @@ -92,11 +92,12 @@ jobs: # # `bun audit` resolves peers from the registry regardless of what is installed, so # neither `--omit=peer` nor `[install] peer = false` keeps react-native's own tree - # out of the graph — only `--ignore` does. These two are metro (react-native's + # out of the graph — only `--ignore` does. These are metro (react-native's # bundler, dev-time only) reached via the react-native peer of # react-native-quick-base64; they are not in a consumer's runtime bundle. Ignores # are per-advisory, so anything new still fails this job. Drop them once - # react-native ships a metro with image-size >= 2.0.3. + # react-native ships a metro with image-size >= 2.0.3 and a patched braces + # (GHSA-vfj7-8cjw-p6xm, via micromatch; no fixed release yet). - name: Audit runtime dependencies run: | mkdir -p /tmp/rnqc-runtime-audit @@ -106,7 +107,8 @@ jobs: bun install --no-summary bun audit --audit-level=high \ --ignore=GHSA-w3rx-r6r6-pgpr \ - --ignore=GHSA-5p2g-fcmc-qvqq + --ignore=GHSA-5p2g-fcmc-qvqq \ + --ignore=GHSA-vfj7-8cjw-p6xm lint_js: name: JS Lint (eslint, prettier) From 1507ff7e567f7bf1ededd5b4e7c5d4be94a0869b Mon Sep 17 00:00:00 2001 From: Brad Anderson Date: Mon, 5 Oct 2026 15:47:33 -0400 Subject: [PATCH 4/4] ci: report tsc errors as check annotations on push reviewdog's github-pr-review reporter needs a PR, so Compile JS (tsc) failed on every push to main. Use github-check outside pull_request events. --- .github/workflows/validate-js.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validate-js.yml b/.github/workflows/validate-js.yml index 9753f2c3..ab53b2c0 100644 --- a/.github/workflows/validate-js.yml +++ b/.github/workflows/validate-js.yml @@ -38,7 +38,8 @@ env: # https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true' -# Minimum scopes — reviewdog posts tsc errors as review comments on PRs. +# Minimum scopes — reviewdog posts tsc errors as review comments on PRs and as +# check annotations on main, where github-pr-review has no PR to report against. permissions: contents: read checks: write @@ -63,7 +64,7 @@ jobs: - name: Run TypeScript # Reviewdog tsc errorformat: %f:%l:%c - error TS%n: %m run: | set -o pipefail - bun tsc 2>&1 | sed 's/^[^ ]* typescript: //' | reviewdog -name="tsc" -efm="%f(%l,%c): error TS%n: %m" -reporter="github-pr-review" -filter-mode="nofilter" -fail-on-error -tee + bun tsc 2>&1 | sed 's/^[^ ]* typescript: //' | reviewdog -name="tsc" -efm="%f(%l,%c): error TS%n: %m" -reporter="${{ github.event_name == 'pull_request' && 'github-pr-review' || 'github-check' }}" -filter-mode="nofilter" -fail-on-error -tee env: REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}