Skip to content

chore(deps): bump @nestjs/core from 11.1.27 to 11.1.28 - #200

Open
dependabot[bot] wants to merge 1 commit into
masterfrom
dependabot/npm_and_yarn/nestjs/core-11.1.28
Open

chore(deps): bump @nestjs/core from 11.1.27 to 11.1.28#200
dependabot[bot] wants to merge 1 commit into
masterfrom
dependabot/npm_and_yarn/nestjs/core-11.1.28

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Jul 8, 2026

Copy link
Copy Markdown
Contributor

Bumps @nestjs/core from 11.1.27 to 11.1.28.

Release notes

Sourced from @​nestjs/core's releases.

v11.1.28 (2026-07-08)

Bug fixes

  • core
    • #17239 fix(core): trigger teardown of SSE producer Observable on client disconnect with interceptor (@​jyx-07)
  • common
    • #17257 fix(common): Add missing exception classes to HttpErrorByCode (@​Se3do)
  • websockets
    • #17188 fix(websockets): correct type guard to check value not key (@​Se3do)

Enhancements

  • core
    • #17241 feat(core): include auto-converted route in legacy route path warning (@​ronielli)

Dependencies

Committers: 4

Commits
  • dfaa376 chore(release): publish v11.1.28 release
  • 053a316 Merge pull request #17239 from jyx-07/fix/sse-interceptor-teardown
  • 8e7a2ee feat(core): include auto-converted route in legacy route path warning
  • c5b7164 fix(core): trigger sse observable teardown on disconnect
  • See full diff in compare view

Note
Automatic rebases have been disabled on this pull request as it has been open for over 30 days.

@dependabot dependabot Bot added dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code labels Jul 8, 2026
Bumps [@nestjs/core](https://github.com/nestjs/nest/tree/HEAD/packages/core) from 11.1.27 to 11.1.28.
- [Release notes](https://github.com/nestjs/nest/releases)
- [Commits](https://github.com/nestjs/nest/commits/v11.1.28/packages/core)

---
updated-dependencies:
- dependency-name: "@nestjs/core"
  dependency-version: 11.1.28
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot
dependabot Bot force-pushed the dependabot/npm_and_yarn/nestjs/core-11.1.28 branch from 5ec6d0d to d0e23c5 Compare July 10, 2026 06:20

@clestons clestons left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — APPROVE [2-round: dependabot bump + CI 核验]

chore(deps): bump @nestjs/core 11.1.27 → 11.1.28

  • 全部 CI check 绿(已核实:build / test / typecheck / lint / security 均 pass;skipping 为路径过滤的正常跳过)。
  • package.json + lockfile 变动,无源码逻辑改动。
  • patch/minor 或 CI 已验证可解析的升级,无 peer 冲突。

结论:APPROVE — 低风险依赖升级,CI 全绿。(合并由维护者/$pr-fix 决定,本 review 不合并。)

jhfnetboy added a commit that referenced this pull request Aug 17, 2026
…d, held)

pr-daemon RC on #237 found two design-level Criticals that dvt cannot fix
unilaterally -- escalated on CC-98, PR held draft:
  B1: sortition curve never requires an honest signer + m<=110 caps the tail
      at ~6.6e-6 (no n reaches 1e-9). Needs DSR's written security target and
      a corrected m/T curve.
  B2: accountId is calldata-trusted and enforcement is cross-repo while
      airaccount #200 is draft -- no interlock; needs airaccount + enrollment.

This commit fixes the SELF-CONTAINED findings (curve-independent, all correct
regardless of how B1 resolves):
- B3 (High): setOversample now bumps configVersion (symmetric with
  setEpochLength) so it cannot retroactively collapse the sortition gate on an
  already-pinned epoch. Test proves a valid op fails-closed after the change.
- Medium: requiredQuorum() reads epochLength directly instead of via
  currentEpoch(), so the default epochLength==0 config returns the fail-closed
  sentinel instead of reverting.
- Medium: snapshotEpoch requires lastSetMutationBlock < block.number, so a
  permissionless syncNode eviction cannot be atomically composed with the
  freeze to depress epochSetCount (feeds B1's budget).
- Low: setEpochLength floor raised to 64 (real pin window is
  min(256, epochLength-1); tiny values leave no keeper window).
- Low: emit SlotAssigned/SlotCleared so aggregators reconstruct frozen trees
  from logs without re-deriving the slot allocator.
- Info: drop unused G1_LEN.
- Coverage: added a DISCRIMINATING look-ahead test (verified: fails on the
  setRoot[e-1]->setRoot[e] mutant) and a syncNode->_deactivate SMT-hook test
  (verified: fails on the hook-deletion mutant). registerWithProof-path hook
  coverage still open (needs stake/PoP mock) -- deferred to the post-B1 pass.

105 tests pass. #237 stays draft pending B1 (DSR) + B2 (airaccount).
jhfnetboy added a commit that referenced this pull request Aug 17, 2026
* feat(CC-98): production per-proposal committee BLS validator

AAStarCommitteeValidator extends AAStarValidator with the converged CC-98
model: per-operation random committee the submitter cannot choose.

- Incremental sparse Merkle commitment of the active set (TREE_DEPTH=14),
  maintained O(depth) via _onNodeActivated/_onNodeDeactivated hooks added to
  the base at every set mutation (register/dereg/revoke/batch).
- snapshotEpoch(): permissionless double-snapshot. seed[e]=blockhash(e*L)
  pinned within the 256-block window; setRoot[e]=runningRoot frozen for use
  ONE EPOCH AHEAD (look-ahead) so the committed set is frozen strictly before
  the seed is revealed -> closes the register-to-order grinding window.
- validate(): per signer verifies Merkle membership in setRoot[e-1] +
  sortition H(CMT_SELECT, seed[e], accountId, nodeId) < T, zero extra
  pairings, then the base aggregate BLS verify. accountId is account-injected
  (root of trust). Threshold requiredQuorum = ceil(2*m_e/3), m_e per the DSR
  curve capped at n. epochLength==0 -> legacy whole-set fallback.

Self-review (4 rounds) fixed two real bugs before commit:
  1. expectedCommittee floor-16 not capped at n -> 9..15 pools had
     quorum > n (unsatisfiable, liveness DoS). Now capped at n.
  2. whole-set (T=max) spuriously excluded a draw==max node (2^-256).
     Now skips the draw when T==max.

18 committee tests + 96 total pass. Base changes are additive virtual hooks
(no behavior change to the legacy validator; all existing tests green).

* style(CC-98): forge fmt committee validator + tests

* fix(CC-98): address Codex adversarial review

Codex Tier-1 review (via codex exec) of PR #237. Code fixes:
- High: setEpochLength rejects epochLength==1 (startBlock==block.number =>
  never pinnable => committee mode permanently dead). Now requires 0 or >=2.
- Medium: submitter now provides the signer's slot in the payload,
  authenticated by the Merkle proof against the FROZEN setRoot[e-1] (each
  nodeId is at one slot in that tree, so a wrong slot cannot verify). Fixes
  the slot-reuse liveness edge where a re-registered node's live slot no
  longer matched its historical slot. Wire adds slot(32)/signer.
- Medium: setOversample bounds num/den ([1,8], den<=1e9) so oversampleNum*m
  in _thresholdOf cannot overflow and turn a fail-closed return-1 into a
  revert (uniform malformed-op handling preserved).
- Low: configVersion namespaces epoch snapshots; setEpochLength bumps it so a
  seed/root pinned under a previous schedule is never reused under a new one
  (validate + requiredQuorum fail-closed until re-pinned).

Documented as SECURITY ASSUMPTIONS (residuals inherent to the architecture,
not code-fixable here):
- accountId is account-injected (router breaks msg.sender binding) — a
  load-bearing account-side invariant (airaccount MUST enforce).
- frozen-member removal is a BFT liveness bound (DSR oversampling + SP
  unbonding + epoch retry mitigate; lowering quorum on churn would break
  safety, intentionally not done).
- missed pin window => <=2-epoch self-healing outage (no grindable late-seed
  fallback); run redundant permissionless keepers.
- caller-chosen freeze time within the pin window is minor fairness griefing,
  not safety (seed still unknowable at freeze).

22 committee tests (4 new for the fixes) + 99 total pass.

* fix(CC-98): resolve Codex round-2 findings (self-introduced by round-1 fixes)

- round-2 High: snapshotEpoch allows re-pinning an epoch whose pin belongs to
  a previous configVersion (else colliding epoch numbers after an epochLength
  change strand committee mode until the counter passes every old ID).
- round-2 Low: validate rejects non-canonical slot (slot >= 2^TREE_DEPTH),
  which _verifyMerkle would otherwise alias to slot mod 2^TREE_DEPTH.

Codex Tier-1: APPROVED - no remaining findings (3 rounds). 24 committee + 99 total pass.

* fix(CC-98): address pr-daemon self-contained findings (B1/B2 escalated, held)

pr-daemon RC on #237 found two design-level Criticals that dvt cannot fix
unilaterally -- escalated on CC-98, PR held draft:
  B1: sortition curve never requires an honest signer + m<=110 caps the tail
      at ~6.6e-6 (no n reaches 1e-9). Needs DSR's written security target and
      a corrected m/T curve.
  B2: accountId is calldata-trusted and enforcement is cross-repo while
      airaccount #200 is draft -- no interlock; needs airaccount + enrollment.

This commit fixes the SELF-CONTAINED findings (curve-independent, all correct
regardless of how B1 resolves):
- B3 (High): setOversample now bumps configVersion (symmetric with
  setEpochLength) so it cannot retroactively collapse the sortition gate on an
  already-pinned epoch. Test proves a valid op fails-closed after the change.
- Medium: requiredQuorum() reads epochLength directly instead of via
  currentEpoch(), so the default epochLength==0 config returns the fail-closed
  sentinel instead of reverting.
- Medium: snapshotEpoch requires lastSetMutationBlock < block.number, so a
  permissionless syncNode eviction cannot be atomically composed with the
  freeze to depress epochSetCount (feeds B1's budget).
- Low: setEpochLength floor raised to 64 (real pin window is
  min(256, epochLength-1); tiny values leave no keeper window).
- Low: emit SlotAssigned/SlotCleared so aggregators reconstruct frozen trees
  from logs without re-deriving the slot allocator.
- Info: drop unused G1_LEN.
- Coverage: added a DISCRIMINATING look-ahead test (verified: fails on the
  setRoot[e-1]->setRoot[e] mutant) and a syncNode->_deactivate SMT-hook test
  (verified: fails on the hook-deletion mutant). registerWithProof-path hook
  coverage still open (needs stake/PoP mock) -- deferred to the post-B1 pass.

105 tests pass. #237 stays draft pending B1 (DSR) + B2 (airaccount).

* feat(CC-98): B2 defense-in-depth — account enrollment + committeeActive view + migration interlock

airaccount locked the B2 account-side design (f444db89): accountId injection
(account-side, mandatory) + these dvt-side pieces (curve-independent, land now):

- committeeActive() view: the account reads validator mode to pick its
  signature framing instead of guessing from payload shape (the shape-collision
  root of the flip-order attack). Same state drives parse + framing => no desync.
- enroll()/unenroll() + enrolledAccount mapping (self-proving: msg.sender IS
  the account). validate() fails closed unless the injected accountId maps to an
  enrolled address. This (a) blocks the flip-order legacy-shaped payload on-chain
  (fabricated accountId prefix -> non-enrolled -> reject) and (b) turns a free
  offline grind over 2^256 accountIds into a gas-metered grind over enrolled
  addresses. Defense-in-depth, NOT a replacement for account-side injection.
- setEpochLength migration-interlock doc: deploy+mount+enroll injecting accounts
  BEFORE flipping committee mode.

Does not touch the sortition m/T math -> independent of B1 (still on DSR).
31 committee tests (4 new: committeeActive, enroll self-proving, unenrolled
fail-closed) + 107 total pass.

* fix(CC-98): B1 — DSR-locked m_e curve + oversample 1.0 (resolves last blocker)

DSR delivered the security target and curve (CC-98 9a9f47c9, Jason-adjudicated):
target ε = P(Poisson(β*m_e) >= ceil(2*m_e/3)) <= 1e-6 per (account, epoch)
under β <= 10%; N>=430 meets 1e-6 even at worst-case β=1/3.

Curve: m_e(N) = N (N<=8); else clamp(ceil(N/5), 17, 86).
- floor 16 -> 17 (16 gave ε=1.02e-6, just over; 17 gives 2.6e-7)
- cap 110 -> 86 (86 is the β=1/3 1e-6 point; 110 was over-provisioned)
- floor(N/5) -> ceil(N/5)
- oversample 1.15 -> 1.0: DSR's calc assumes E[committee]=m_e (λ=β*m_e); any
  oversample>1 inflates λ and breaks the N>=430 β=1/3 razor-thin margin.

Independently verified the whole ε table with an exact log-space Poisson tail
(matches DSR row-for-row: N=20 2.55e-7, N=100 2.93e-8, N=150 8.3e-11,
N=300 4.8e-20, N=430 β=1/3 9.77e-7). Sampling regime (N>=17) meets ε<=1e-6;
the N<=16 bootstrap band is whole-set, governed by the structural 2/3-of-nodes
argument (impossible at β<=10%) — airaccount's N0 gate keeps small pools off
the sampling path.

Added pr-daemon's B1 discriminators: a DSR-table triple test (m_e,
requiredQuorum) and a monotonicity test (m_e non-decreasing in N => ε
non-increasing, closing 'security worsens as the pool grows').

110 tests pass.

* fix(CC-98): B4 — reject non-canonical accountId (high 96 bits must be zero)

pr-daemon round-2 B4: the enrollment gate reads accountId's low 160 bits but
the sortition draw consumes all 256, so the high 96 bits were a free offline
grind surface (probe: 232 tries to find a high-bit value whose low 160 still
map to an enrolled address, flipping the same attacker committee from reject to
accept). Fix: reject any accountId with non-zero high bits (symmetric to the
canonical-slot check), and correct the false 'gas-metered grind' natspec claim.

Tests: non-canonical accountId rejected, 300-iteration high-bit grind all
rejected, requiredQuorum sentinel pinned to max (not fail-open 0). 36 committee
tests pass. NOT pushed — held with B5 (needs an architectural decision).

* fix(CC-98): B5 two-tail curve (loose-liveness, Jason-adjudicated) + round-2 follow-ups

B5 (Blocking): B1's floor-17/oversample-1.0 curve was single-tailed — ~6.3% of
(account,epoch) had NO satisfiable signer set (honest-liveness stall). Jason's
call: a liveness miss is a retryable one-epoch stall (not fund loss), so hold it
to a LOOSER target than forgery. Verified two-tail operating point (exact
Binom/Poisson scan over n in [9,20000]):
  m_e(N) = clamp(ceil(N/5), 30, 86), oversample = 1.25
  forgery @β<=10% <= ~4.4e-9 (sampling regime)  [target 1e-6]
  liveness <= 1.65e-4 (100% online) / 5.9e-4 (95% online)  [loose target 1e-3]
floor 30 (up from 17) buys the forgery headroom to afford oversample 1.25;
floor 17 could not (its forgery tail was 4.6e-7, razor thin). Gives up the old
β=1/3 'free gift' (out of scope under β<=10%). Cost: requiredQuorum 20..58,
~10KB (N<=150) .. ~29KB (N>=430) calldata/op — far below the strict-liveness
34-51KB. Added a two-tail table test (asserts E[committee] clears quorum) and a
constructor-oversample pin.

round-2 follow-ups:
- High: lastSetMutationBlock revert was a zero-capital migration-boundary DoS
  (setRequireStake(true) makes every bootstrap node permissionlessly
  syncNode-able; a forced same-block collision could block pinning a whole
  epoch). Replaced with a block-start LATCH: snapshotEpoch freezes the
  pre-mutation root/count when the set changed in its own block, and is now
  UNCONDITIONAL (no revert). Discriminating test added (verified via mutation).
- Medium: unenroll() natspec no longer suggests the self-bricking order; warns
  instead.

B4 (prior commit ea1e6a7): reject non-canonical accountId.

115 tests pass.

* fix(CC-98): resolve forge-coverage stack-too-deep in validate()

The Smart Contracts CI job runs `forge coverage`, which disables via-IR (the
optimizer that makes the frame fit) — so validate()'s large frame failed to
compile there (Stack too deep), even though forge build/test (via_ir=true)
compiled fine. Refactor to stay within the non-via-IR stack limit:
- extract the per-signer membership+sortition loop into _verifyCommitteeSigners
- pack its params into a memory _Ctx struct (one stack word, not four)
- block-scope the parse/quorum intermediates in validate()
No behavior change: 115 tests pass; verified the exact coverage compile
condition (FOUNDRY_VIA_IR=false FOUNDRY_OPTIMIZER=false) now succeeds with zero
stack-too-deep. (Security Audit CI failure is pre-existing npm-dep advisories,
unrelated to contracts.)

* fix(CC-98): restore uniform fail-closed + add sortition regression tests (pr-daemon round-3)

The forge-coverage refactor (59cf455) introduced a behavior regression and
exposed a pre-existing coverage hole in the core mechanism:

1. Regression (mine): the refactor moved the accountId calldata slice ahead of
   the length guard, so signature.length < 32 REVERTED instead of returning 1,
   breaking the base contract's uniform fail-closed. Fix: hoist
   `if (signature.length < 32 + G2_LEN) return 1` to the top of the committee
   path, before ANY slice. Regression test: empty / 4-byte / 31-byte sigs all
   return 1 (verified via mutation: reverting the order makes it revert again).

2. Coverage hole (pre-existing, dismissed the false APPROVE): the sortition draw
   had NO regression protection — the account-binding test guarded its only
   assert behind `if (someExcluded)`, which was always false, so deleting the
   entire draw check left 115/115 green. Replaced with:
   - test_validate_sortition_rejects_noncommittee_signer: baseline committee
     validates; swapping one member for a non-committee (but registered +
     Merkle-valid) node must be rejected BY SORTITION. Verified discriminating:
     deleting the draw check flips it 1->0 (RED).
   - test_validate_committee_is_account_bound: same members rejected for a
     different account; asserts unconditionally (require someExcluded).

Coverage still compiles (0 stack-too-deep). 117 tests pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant