Skip to content

fix(sdk): enforce the server's limit contract when lowering document queries - #4434

Merged
QuantumExplorer merged 1 commit into
v4.2-devfrom
fix/document-limit-lowering-contract
Aug 21, 2026
Merged

fix(sdk): enforce the server's limit contract when lowering document queries#4434
QuantumExplorer merged 1 commit into
v4.2-devfrom
fix/document-limit-lowering-contract

Conversation

@PastaPastaPasta

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

The DocumentQueryDriveDocumentQuery lowering diverges from the server's limit contract in three proof-sensitive ways. SizedQuery::limit is part of the reconstructed path query, so each divergence lets an untrusted transport pair a request the server would refuse (or answer differently) with a genuine proof produced for another query — the pre-existing FromProof verification path for Documents is affected today:

  1. An omitted limit lowered to limit: None — unbounded in SizedQuery — while the server applies config.default_query_limit before building the path query. A malicious node could attach an authenticated proof covering every matching document to a request that legitimately proves at most the default.
  2. Explicit limits 101..=65535 passed through, though the server refuses them with InvalidLimit before answering.
  3. Limits above u16::MAX were silently truncated by an as cast (65537 became 1).

Split out of #4389 so that PR stays a pure refactor: its new verify_documents_response entry point delegates through this lowering and needs this contract, so #4389 is stacked on this PR.

What was done?

The lowering now mirrors DriveDocumentQuery::from_typed_clauses exactly: the 0 sentinel falls back to Some(DEFAULT_QUERY_LIMIT) (the compile-time value of config.default_query_limit, 100), and anything above the cap is refused with the server's own Error::Drive(QuerySyntaxError::InvalidLimit).

How Has This Been Tested?

cargo test -p dash-platform-queries: a regression test pins the full contract — unset → Some(100), at-cap passthrough, and rejection (with the typed InvalidLimit variant) for 101, 65535, 65537 (the old truncation case) and u32::MAX. Full dash-sdk build and lib tests.

Breaking Changes

Callers of the conversion see Some(100) where they previously saw None for an omitted limit, and InvalidLimit instead of silent acceptance/truncation for over-cap ones. No in-tree caller depends on the old shapes. The verifier consequence: parity targets the canonical configuration — an operator who raises default_query_limit above 100 serves limits this lowering refuses; the SDK cannot observe per-operator tuning, and proof bytes must not depend on it.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

…queries

The DocumentQuery to DriveDocumentQuery lowering diverged from the server's DriveDocumentQuery::from_typed_clauses in three proof-sensitive ways: an omitted limit lowered to None, which SizedQuery treats as unbounded while the server applies config.default_query_limit, so a malicious node could attach an authenticated proof covering every matching document to a request that legitimately proves at most the default; explicit limits 101..=65535 passed through even though the server refuses them with InvalidLimit before answering; and limits above u16::MAX were silently truncated by an as cast (65537 became 1). Lower the sentinel to the compile-time default and refuse over-cap limits with the server's own InvalidLimit instead of truncating or passing through.

Callers of the conversion see Some(100) where they previously saw None for an omitted limit, and Error::Drive(QuerySyntaxError::InvalidLimit) instead of silent acceptance for over-cap ones. No in-tree caller depends on the old shapes; the pre-existing FromProof-for-Documents verification path inherits the fix.
@github-actions github-actions Bot added this to the v4.2.0 milestone Aug 20, 2026
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@PastaPastaPasta, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 59 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f225bded-1944-4bf1-9e4a-701f39b4e6fb

📥 Commits

Reviewing files that changed from the base of the PR and between 837b5ef and 9f82577.

📒 Files selected for processing (2)
  • packages/dash-platform-queries/src/documents/document_query.rs
  • packages/dash-platform-queries/tests/document_limit_lowering.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@thepastaclaw

thepastaclaw commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

✅ Final review complete — no blockers (commit 9f82577)

@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 19.04762% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.08%. Comparing base (837b5ef) to head (9f82577).

Files with missing lines Patch % Lines
...h-platform-queries/src/documents/document_query.rs 19.04% 17 Missing ⚠️

❌ Your patch check has failed because the patch coverage (19.04%) is below the target coverage (50.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff              @@
##           v4.2-dev    #4434      +/-   ##
============================================
- Coverage     87.21%   87.08%   -0.14%     
============================================
  Files          2729     2729              
  Lines        347524   347994     +470     
============================================
- Hits         303110   303037      -73     
- Misses        44414    44957     +543     
Components Coverage Δ
dpp 88.96% <ø> (ø)
drive 86.27% <ø> (-0.05%) ⬇️
drive-abci 89.45% <ø> (-0.25%) ⬇️
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value 92.92% <ø> (ø)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier 47.14% <ø> (-0.27%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Final validation — Codex/Sol only (Phase 2 disabled)

The exact-head diff correctly maps an omitted document limit to the canonical default, rejects every value above the server cap before narrowing to u16, and preserves the typed InvalidLimit error. The regression test covers the default, boundary, over-cap, former truncation, and maximum-u32 cases; no in-scope defects were found.
Source: reviewer backend model gpt-5.6-sol (general, security-auditor, and rust-quality lanes); final verifier backend model gpt-5.6-sol; orchestration-only openclaw-agent/cliproxy/gpt-5.6-sol (not reviewer evidence).

Validated zero-blocker Codex/Sol precheck evidence was promoted to final because Phase 2 (Sonnet/Opus) is temporarily disabled. This is Codex/Sol-only final validation, not Codex + Sonnet/Opus coverage.

Review provenance

  • Codex reviewers: gpt-5.6-sol — general (completed), gpt-5.6-sol — security-auditor (completed), gpt-5.6-sol — rust-quality (completed)
  • Verifier: gpt-5.6-sol — verifier
  • Sonnet/Opus: not run (Phase 2 disabled — temporary Codex/Sol-only final)
  • Secondary pass: disabled (temporary_phase2_sonnet_disable)

@PastaPastaPasta

Copy link
Copy Markdown
Member Author

Note on the red codecov/patch: the new lowering branches are all exercised — tests/document_limit_lowering.rs drives unset (→ Some(100)), at-cap, and each rejection case (101, 65535, 65537, u32::MAX) including the typed InvalidLimit match — but the coverage job does not attribute this package's integration-test runs, so the patch metric reads 19%. The gate is advisory in this repo (#4388 merged with it red for the same reason). Every functional check is green and thepastaclaw's gate passed with no blockers.


🤖 Posted autonomously by Claude on behalf of pasta.

@QuantumExplorer
QuantumExplorer merged commit 98bb0aa into v4.2-dev Aug 21, 2026
17 of 18 checks passed
@QuantumExplorer
QuantumExplorer deleted the fix/document-limit-lowering-contract branch August 21, 2026 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants