Test unconfigured-contract 502 path, guard single-primary wallet, dedupe pnpm allowlist, test shared/jwt - #161
Merged
dev-fani merged 2 commits intoAug 30, 2026
Conversation
…upe pnpm allowlist; test shared/jwt Closes fanilabs#130 Closes fanilabs#129 Closes fanilabs#128 Closes fanilabs#127 fanilabs#130 — Every module's `createUnconfiguredContractClient()` 502 BLOCKCHAIN_ERROR fallback (the documented behavior when a `*_CONTRACT_ID` is blank) had no test. Adds one integration case per module (deliveries, escrow, fleet, disputes, reputation) that mints an access token, calls a build endpoint with the contract id unset, and asserts a 502 whose `code` is BLOCKCHAIN_ERROR and whose message names the missing env var — so a broken ternary or a message losing the variable name is caught. Narrows `vitest.config.ts`'s blanket `src/**/index.ts` coverage exclusion to barrel/re-export index files only, so the five composition roots' conditional wiring is no longer hidden from the coverage report. fanilabs#129 — `confirmWalletLink` set `isPrimary` from a race-prone check-then-create, so two concurrent confirmations for a brand-new user could both become primary. Adds a Postgres partial unique index (`wallet_addresses_user_id_primary_key ON wallet_addresses(user_id) WHERE is_primary`) via a hand-written migration (Prisma's DSL can't express a filtered unique index; a note on the model records why). `confirmWalletLink` now catches the constraint violation on the first-wallet path and retries as non-primary, preserving "first wallet wins" instead of 500-ing the loser. fanilabs#128 — The native-build-script allowlist was declared twice: in `package.json`'s `pnpm.onlyBuiltDependencies` and `pnpm-workspace.yaml`'s `allowBuilds`. `onlyBuiltDependencies` is removed in pnpm v11, so a `packageManager` bump past v11 could silently disable it and re-introduce the Phase 6 bcrypt/Prisma build regression. Removes the `package.json` copy, leaving `allowBuilds` as the single source of truth; notes the move in `docs/DEPLOYMENT.md` § Status. fanilabs#127 — `src/shared/jwt` (the token module every protected route trusts) had no dedicated test. Adds `src/shared/jwt/index.spec.ts` covering all four functions directly: claim round-trips, wrong secret, expired token, tampered payload, and access/refresh purpose confusion.
|
@driftsorbit Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Four small, independent reliability/testing fixes.
Closes #130
Closes #129
Closes #128
Closes #127
#130 — 502
BLOCKCHAIN_ERROR-on-unconfigured is now tested, and no longer hidden from coverageEach of
deliveries,escrow,fleet,disputes,reputationhas acreateUnconfiguredContractClient()in its composition-rootindex.tswhose methods throw aBlockchainErrorwhen the module's*_CONTRACT_IDis blank (the.env.exampledefault).docs/API_REFERENCE.mddocuments this 502 for every one of the five, but no integration spec exercised it, andvitest.config.tsexcluded everyindex.tsfrom coverage so the branch was invisible there too.*-routes.integration.spec.ts: mints an access token withsignAccessToken, POSTs a valid body to a build endpoint with the contract id unset (the test-process default), and assertsstatusCode === 502,error.code === 'BLOCKCHAIN_ERROR', and that the message names the missing env var. Each fails if the module's fallback wiring (theconfig.X_CONTRACT_ID ? real : fallbackternary) is removed or the message drops the variable name. These run under the samedescribe.skipIf(!dbAvailable)gate as the rest of each file.src/**/index.tstosrc/**/{domain,application,infrastructure,interface}/index.ts+src/shared/**/index.ts. Genuine barrel/re-export files stay excluded; the five module composition roots with real conditional logic are now reported.#129 — concurrent wallet-link confirmations can't both become
isPrimaryconfirmWalletLinkchoseisPrimaryfromcurrentWallets.length === 0then calledcreate, with nothing at the DB level stopping two concurrent confirmations for a brand-new user from both winning that check.20260830120000_wallet_address_single_primaryadds a Postgres partial unique index:CREATE UNIQUE INDEX wallet_addresses_user_id_primary_key ON wallet_addresses(user_id) WHERE is_primary;— any number of non-primary rows per user, at most one primary. Prisma's schema DSL can't represent a filtered unique index, so it lives only in the hand-written migration; a comment on theWalletAddressmodel records this so nobody "resolves drift" by dropping it.confirmWalletLinknow, on the first-wallet path, catches the constraint violation and re-links the wallet as non-primary (after confirming a primary now exists), so the loser of the race still succeeds — "first wallet wins" — rather than getting a 500. Non-race behavior is unchanged.confirm-wallet-link.spec.ts); integration test firing two concurrentcreate({ isPrimary: true })for one user and asserting exactly one survives as primary and the other can still be linked non-primary (prisma-repositories.integration.spec.ts).#128 — the pnpm native-build allowlist was declared twice
package.json'spnpm.onlyBuiltDependenciesandpnpm-workspace.yaml'sallowBuildsheld the identical six-package list.allowBuilds(pnpm v10.26.0+) is the replacement;onlyBuiltDependenciesis removed in pnpm v11, so apackageManagerbump past v11 could silently disable the allowlist and re-introduce the Phase 6 bcrypt/Prisma "native build scripts skipped on clean install" regression thatdocs/DEPLOYMENT.md§ Status records fixing.pnpm.onlyBuiltDependenciesfrompackage.json;allowBuildsis now the single source of truth (with a comment explaining why).docs/DEPLOYMENT.md§ Status item 3 to reflect the single location and the reason for the move.pnpm installin a pnpm-v11 / Dockerfile-base container to re-confirm the six packages still build with onlyallowBuildspresent is left for a maintainer with that environment — this PR is config-only for that item.#127 —
src/shared/jwthad no dedicated testsignAccessToken/verifyAccessToken/signRefreshToken/verifyRefreshToken— trusted by the shared HTTP auth guard on every protected route — were only covered incidentally by theauthmodule's flow tests. Addssrc/shared/jwt/index.spec.tstesting all four directly: claim round-trips, wrong-secret rejection, expired-token rejection, tampered-payload rejection, and access/refresh purpose confusion in both directions.Verification
pnpm run typecheck— no new errors (the repo has 52 pre-existingtsc --noEmiterrors onmain, all in files this PR doesn't touch; count unchanged).pnpm exec vitest run src/shared/jwt/index.spec.ts src/modules/users/application/confirm-wallet-link.spec.ts— 17 passed.eslintandprettierclean on all changed files.