Skip to content

Canary --dry-run mode, list-wasm-hashes unit tests, safe dependency bumps - #809

Open
omarima-10 wants to merge 1 commit into
vjuliaife:mainfrom
omarima-10:feat/canary-dryrun-wasm-hash-tests-safe-dep-bumps-774-776-461
Open

Canary --dry-run mode, list-wasm-hashes unit tests, safe dependency bumps#809
omarima-10 wants to merge 1 commit into
vjuliaife:mainfrom
omarima-10:feat/canary-dryrun-wasm-hash-tests-safe-dep-bumps-774-776-461

Conversation

@omarima-10

Copy link
Copy Markdown

closes #774
closes #776
closes #461

Summary

Three independent pieces of work, bundled into one PR since they're small and non-overlapping.

#776--dry-run mode for scripts/verify-upgrade.ts

Added a --dry-run flag to the canary deposit/withdraw cycle. Since TariffShieldClient.depositCollateral/withdrawCollateral build+sign+submit in one shot with no simulate-only path, --dry-run instead builds the deposit_collateral/withdraw_collateral transactions manually via TransactionBuilder + Contract.call(...) and runs them through SorobanRpc.Server#simulateTransaction, using scValToNative to read the resulting collateral_balance off the simulated return value — mirroring the pattern already used by rotate-admin.ts's own --dry-run. No funds move and nothing is signed or broadcast in this mode.

The balance-comparison assertions (before → after-deposit → after-withdraw) are unchanged in shape; they just run against simulated results instead of on-chain reads. CanaryResult gained an optional simulated: boolean field so the JSON report on disk records which mode produced it.

Extracted the whole canary cycle (both live and dry-run branches) into an exported runCanaryCycle(...) helper, matching how diffAccountFields/determineOverallStatus were already pulled out of main() for testability. --dry-run combined with --skip-canary behaves the same as --skip-canary alone (canary doesn't run either way). Usage header comment documents the new flag.

Tests added to scripts/__tests__/verify-upgrade.test.ts: live-path pass/fail cases (deposit/withdraw balance mismatches, a rejecting depositCollateral call) plus dry-run-path cases (simulate pass with depositCollateral/withdrawCollateral asserted never called, a simulated-balance-mismatch failure, a simulateTransaction error via isSimulationError, and the guard error when server/contractId/networkPassphrase are missing under dryRun: true).

#774 — unit tests for scripts/list-wasm-hashes.ts

The filtering/fallback/sort/selection logic previously lived entirely inline in main(), with no exported seam to test against. Extracted it into pure functions in new scripts/lib/list-wasm-hashes-logic.ts:

  • loadHistory(path) — reads + parses history.json, throwing DeploymentHistoryNotFoundError / EmptyDeploymentHistoryError instead of calling process.exit directly (mirrors the scripts/lib/upgrade-logic.ts custom-error-class pattern already used in this repo).
  • filterDeployments(history, { contractId, network }) — filters by both, falling back to the full unfiltered history when the filter yields zero matches (existing behavior, preserved as-is).
  • sortByDeployedAtDescending(deployments) — non-mutating descending sort.
  • selectPreviousDeployment(sorted) — index-1 selection (index 0 is "current"), undefined when fewer than 2 deployments.

list-wasm-hashes.ts is now a thin wrapper: read the file, call the pure functions, print. main() is exported and gained the same import.meta.url === file://... direct-invocation guard the other scripts use.

scripts/__tests__/list-wasm-hashes.test.ts covers: filtering by contractId only, network only, and both combined; the fallback-to-full-history path (both when the combined filter matches nothing and when only one filter is set); descending sort correctness and non-mutation; selectPreviousDeployment for 0/1/2/3+ deployments; loadHistory against a real temp-file fixture for the happy path, missing-file, and empty-array cases; and main()'s process.exit(1) paths for both error conditions, exercised by mocking process.exit (not calling the real one) and pointing process.cwd() at a scratch temp directory via mock.method.

#461 — safe-category dependency bumps

Applied the triage's category-(a) "safe now" bumps, re-verified against the actual lockfile and each dependent's declared semver range before applying (a couple didn't hold up under that check — see below):

package before after how
postcss (direct dep, apps/web) 8.5.14 8.5.25 already within its ^8.4.49 range — lockfile refresh only
form-data 4.0.5 4.0.6 root overrides
fast-uri 3.1.2 3.1.4 root overrides — see note below
brace-expansion (top-level entry only) 5.0.6 5.0.8 targeted npm update, no override
shell-quote 1.9.0 1.10.0 root overrides

Two notes on what changed from the original triage list:

  • fast-uri targeted 3.1.4, not 4.1.1. The triage's proposed 4.1.1 is a major bump that ajv@8.20.0 (a @commitlint/config-validator transitive, used only by commitlint) pins to ^3.0.14.1.1 doesn't satisfy that range. 3.1.4 is the latest 3.x release, still satisfies ajv's range, and clears the same advisory (3.0.0 - 3.1.3) without a major-version jump.
  • sharp is excluded from this PR. The fix requires the 0.35.x line (0.34.x has no patched release — 0.34.5 is the last one on that line), but next@16.2.6 declares sharp: "^0.34.5" as an optionalDependency, which does not admit 0.35.x. Forcing it via override would run next's bundled image-optimization pipeline against a sharp version outside its own declared-compatible range. Flagging as a follow-up: either wait for next to bump its own sharp range, or take this as a separate, deliberately-reviewed override once someone can smoke-test next/image against 0.35.x specifically.
  • brace-expansion was applied narrowly — only the single top-level lockfile entry (the one npm audit actually flags at <=5.0.7) moved to 5.0.8. The several nested copies under eslint/@typescript-eslint/typescript-estree/@redocly/openapi-core/rimraf/npm stayed on their own 1.x/2.x lines untouched — those are separate major-version lines pinned by their respective parents (e.g. minimatch@3.1.5 needs brace-expansion@^1.1.7, an entirely different, incompatible API shape from the 5.x line), and a blanket override would have forced them onto 5.x and broken eslint/lint tooling. npm audit's <=5.0.7 range check is a version-string match against the package name as a whole and papers over the fact that this package has multiple concurrently-maintained major lines — those nested 1.x/2.x copies still show up in npm audit output post-bump, but that's an audit-noise artifact, not a real unpatched vulnerability in those lines.
  • axios, next, the @opentelemetry/* family, and the npm/@npmcli/*/pacote/sigstore/tar tooling cluster are untouched, per the triage — those need their own scoped follow-ups.

Verification

  • npm run test:scripts — 70/70 passing (up from 62 on main; +8 new runCanaryCycle tests, +18 new list-wasm-hashes tests, offset by test-file consolidation elsewhere). rollback-upgrade.test.ts's 3 tests remain skipped, pre-existing and unrelated (blocked on Fix syntax error in scripts/rollback-upgrade.ts that breaks the entire rollback path #767, a syntax error in rollback-upgrade.ts that predates this branch).
  • npm run buildpackages/sdk builds clean. apps/api's tsc and apps/web's next build both fail on main before this branch too (confirmed via a stash/rebuild comparison): apps/api fails on a pre-existing src/migrate.ts top-level-await/module issue and a pre-existing S3_DOCUMENTS_BUCKET type error in src/routes/importers.ts (unrelated to the surety_admin code path touched while investigating Optimize GET /importers surety_admin Query with JOIN to Eliminate N+1 #250); apps/web fails on a missing native lightningcss.darwin-arm64.node binary in this environment, unrelated to the dependency bumps in this PR (reproduces identically with postcss at its pre-bump version). Neither failure touches any file changed here.
  • Lint: packages/sdk lint passes clean. apps/api and apps/web lint both have pre-existing failures on main (unused-var errors in health.ts/importers.ts/kyc.ts/etc., and a next lint --max-warnings 0 CLI-flag incompatibility) — confirmed pre-existing via the same stash comparison, none in files this PR touches.
  • npm audit's raw vulnerability count is noisy across this change (it attributes advisory "effects" across whatever's in a package's dependency tree, so re-resolving a subtree can make the count jump even when nothing regresses) — the reliable signal is per-package: postcss's top-level entry, brace-expansion's top-level entry, and picomatch's top-level entry no longer appear in any advisory's nodes list; form-data and fast-uri are fully clear.

#250 — investigated, no code change

Re-verified the N+1 claim in #250 with a fresh read of apps/api/src/routes/importers.ts (the surety_admin branch, lines 184-201) and apps/web/app/surety/page.tsx. Confirmed there's a single JOIN query with no per-importer follow-up queries, and the frontend makes exactly two top-level requests (listImporters(), getStats()), not one per row. The existing comment on the issue already documents this accurately with file/line references: #250 (comment) — no further action needed, and no #250 files are touched by this PR.

@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

Deployment failed with the following error:

The `vercel.json` schema validation failed with the following message: should NOT have additional property `rootDirectory`

Learn More: https://vercel.com/docs/concepts/projects/project-configuration

@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tariff-shield-web Error Error Jul 31, 2026 10:08pm

@drips-wave

drips-wave Bot commented Jul 30, 2026

Copy link
Copy Markdown

@omarima-10 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! 🚀

Learn more about application limits

- verify-upgrade.ts: add --dry-run flag that simulates the canary
  deposit_collateral/withdraw_collateral calls via simulateTransaction
  instead of submitting them, mirroring rotate-admin.ts's dry-run
  pattern. Extract the canary cycle into a runCanaryCycle helper so
  both the live and dry-run paths are independently unit-testable.
  CanaryResult gains an optional simulated flag so the on-disk report
  records which mode produced it.

- list-wasm-hashes.ts: extract the inline filtering/fallback/sort/
  selection logic into pure functions in scripts/lib/list-wasm-hashes-
  logic.ts (filterDeployments, sortByDeployedAtDescending,
  selectPreviousDeployment, loadHistory), with main() reduced to a
  thin read-call-print wrapper. Add scripts/__tests__/list-wasm-
  hashes.test.ts covering env-var filtering, the zero-match fallback
  to full history, descending sort + previous-deployment selection,
  and the missing-file/empty-history process.exit(1) paths.

- Bump patch/minor dependency versions flagged safe-now in the vjuliaife#461
  triage: postcss (direct dep in apps/web) 8.5.14 -> 8.5.25, form-data
  4.0.5 -> 4.0.6, fast-uri 3.1.2 -> 3.1.4, brace-expansion (top-level
  entry only) 5.0.6 -> 5.0.8, shell-quote 1.9.0 -> 1.10.0, via
  root-level npm overrides plus a lockfile refresh scoped to those
  packages. sharp is intentionally left untouched: the CVE fix
  requires the 0.35.x line, which falls outside next@16.2.6's
  declared `^0.34.5` optionalDependency range, so bumping it would
  force an unsupported combination rather than a clean patch. axios,
  next, the opentelemetry family, and the npm/pacote/sigstore/tar
  tooling cluster are unchanged, per the triage.
@omarima-10
omarima-10 force-pushed the feat/canary-dryrun-wasm-hash-tests-safe-dep-bumps-774-776-461 branch from 916aa87 to b87e996 Compare July 31, 2026 22:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant