Skip to content

sdk%lint: introduce CodeQL and semgrep linters, add shim, derivation, disambiguation rules, resolve violations, add common helper for lint infra#5

Merged
kwvg merged 17 commits into
dashpay:developfrom
kwvg:lint_syn
Jun 6, 2026

Conversation

@kwvg

@kwvg kwvg commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

Motivation

The next few pull requests will be streamlining the codec infrastructure and common traits expected from consensus-defining types. As part of preparing the codebase for these changes, we needed a way to implement the Development Guide programatically to ensure that codebase consistency, maintainability and a saner public API.

This is achieved through semantic analysis (using CodeQL) and textual analysis (using semgrep). Both have limitations, namely that CodeQL's Rust support is relatively new (only a year old, see blog) and lacks file:line querying equivalent to Java or C++ (example) and semgrep has no positional awareness.

So with the help of some linter preprocessing, we can achieve partial file:line awareness while allowing semgrep to more efficiently implement rules that can be represented in RegEx. This should give us enough flexibility to at a minimum, prevent regressions in code quality.

Additional Information

  • Dependency for sdk%feat: introduce trait BaseCodec and {impl,codec}_* helper macros to reduce boilerplate, enforce create::prelude use, drop premature limits #4

  • CodeQL is not open-source software. The libraries, queries and other scaffolding are MIT-licensed (see github/codeql) but the engine (at github/codeql-cli-binaries) is subject to proprietary license terms (source)

    • These terms permit us to use CodeQL without obtaining a license for GitHub Advanced Security (a paid offering) as we fulfil the criteria laid out for unpaid use.

      • dashpay/base-sdk is MIT-licensed and hosted and maintained on GitHub

      • Our CI/CD infrastructure is based on GitHub Actions, hosted on Github.com

    A change in either conditions would require us to re-evaluate our CodeQL usage though the alternatives are not encouraging.

  • Implementing skip support (required as CodeQL is a time-consuming step) required commonly agreed return codes which prompted a refactoring of the Python lint infrastructure in the form of introducing a common helper and moving to exception-based early-exit.

    Skip support is absent for all other tests and will fail if the required binaries are missing.

  • Because CodeQL requires compilation, the lint runner and MSRV job in the stable build runner were merged together and spun off, this means we lose per-crate MSRV validation (but this is compensated for by workspace MSRV validation) which should additionally compensate moving away from the single vCPU runner due to the overall fewer jobs executed.

    The lint and build jobs are parallel as CodeQL is sufficiently time-consuming that the MSRV build and validate is faster. The benefit of caching that comes from a sequential build is minimal.

Breaking Changes

None expected.

How Has This Been Tested?

cargo test --features full,_internal
./contrib/lint/all_lint.py

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 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)

@kwvg kwvg added this to the 0.1 milestone Jun 2, 2026
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Looking for one thing? Review this PR in Change Stack to search files, summaries, diffs, and code without losing your place.

Review Change Stack

📝 Walkthrough

Walkthrough

This PR establishes comprehensive static analysis infrastructure by reorganizing CI workflows, consolidating Python lint tooling with shared helpers, deploying custom CodeQL libraries and queries for Rust analysis, integrating Semgrep pattern matching, and enforcing consistent coding standards across the codebase.

Changes

Static Analysis Infrastructure

Layer / File(s) Summary
CI workflow reorganization
.github/workflows/build_msrv.yml, .github/workflows/build_stable.yml, .github/workflows/build_nightly.yml, .github/workflows/pr_comment.yml, .github/workflows/pr_tag.yml
MSRV builds moved to separate build_msrv.yml pipeline with lint and build jobs; build_stable.yml simplified to remove MSRV job; legacy lint_all.yml removed; develop-branch filters added to push triggers; cargo cache keys simplified across all workflows to depend only on Cargo.lock.
Shared Python lint framework
contrib/lint/common.py
New module introduces RETCODE_ERR/RETCODE_PASS/RETCODE_SKIP constants, find_up() for parent directory traversal, is_workspace_root() for workspace detection, and require_bin() for executable resolution with Windows support.
Existing lint script modernization
contrib/lint/all_lint.py, contrib/lint/lint_javascript.py, contrib/lint/lint_python.py
Scripts refactored to use shared common helpers for binary discovery and repository navigation; all_lint.py standardized to use shared return-code constants; error handling improved with exception wrapping in __main__ blocks.
CodeQL library infrastructure
contrib/codeql/lib/files.qll, contrib/codeql/lib/filters.qll, contrib/codeql/lib/fmt.qll, contrib/codeql/lib/imports.qll, contrib/codeql/lib/policy.qll, contrib/codeql/lib/traits.qll
Reusable CodeQL libraries provide location/path utilities, type filtering by context (local/test/macro-generated), string formatting, import preamble group analysis, serde trait detection, trait implementation classification, and security/encoding policies for Rust types.
CodeQL analysis queries
contrib/codeql/attrib.ql, contrib/codeql/import.ql, contrib/codeql/secret.ql, contrib/codeql/qlpack.yml, contrib/codeql/codeql-pack.lock.yml, contrib/codeql/.gitignore
Three problem queries detect missing trait/serde derivations, import ordering violations, and secret type Debug derivations; CodeQL pack metadata and lockfile pin dependencies; gitignore excludes generated artifacts and test patterns.
CodeQL and Semgrep lint scripts
contrib/lint/lint_codeql.py, contrib/lint/lint_semgrep.py
lint_codeql.py auto-generates source-line predicates, runs CodeQL format checks, creates Rust databases, executes queries, and reports findings; lint_semgrep.py discovers patterns, runs scans over pkgs/, and maps exit codes consistently.
Semgrep rules and policy documentation
contrib/semgrep/prelude.yml, contrib/semgrep/serde.yml, CLAUDE.md, docs/guide_rust.md
Semgrep rules enforce crate::prelude wildcard imports and disambiguated serde derivation syntax; trait derivation guidance updated to remove Default from recommended eager derivations; pyproject.toml and pkgs/primitives/Cargo.toml updated for new dependencies and feature flags.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description provides context about the motivation for linting infrastructure, technical decisions, licensing, testing approach, and checklist completion, all related to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately captures the main changes: introduction of CodeQL and semgrep linters, infrastructure refactoring, and rule implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown

Warning

This pull request may have conflicts, please coordinate with the authors of these pull requests.

Potential conflicts

@kwvg kwvg changed the title sdk%lint: introduce syn-based linter, add shim, derivation, disambiguation rules, resolve violations, add common helper for lint infra sdk%lint: introduce CodeQL and semgrep linters, add shim, derivation, disambiguation rules, resolve violations, add common helper for lint infra Jun 5, 2026
@kwvg

kwvg commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (3)
.github/workflows/build_msrv.yml (1)

21-24: 💤 Low value

Optional security hardening: consider setting persist-credentials: false.

For defense-in-depth, consider explicitly setting persist-credentials: false in checkout steps to prevent the GITHUB_TOKEN from persisting in the workspace and potentially leaking through artifacts or logs.

🔒 Set persist-credentials to false
       - name: Checkout
         uses: actions/checkout@v6
         with:
           fetch-depth: 0
+          persist-credentials: false

And for the build job:

       - name: Checkout
         uses: actions/checkout@v6
+        with:
+          persist-credentials: false

Also applies to: 92-93

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build_msrv.yml around lines 21 - 24, The checkout steps
using actions/checkout@v6 (the step with name "Checkout" and any other
actions/checkout@v6 occurrences) should explicitly set persist-credentials:
false under the with: block to avoid persisting GITHUB_TOKEN in the workspace;
update the with: block on the existing checkout step (currently containing
fetch-depth: 0) and any other checkout steps in the file to include
persist-credentials: false while preserving existing keys like fetch-depth.
contrib/lint/lint_codeql.py (1)

65-74: 💤 Low value

Simple substring matching may produce false positives.

The checks if "Serialize" in line: and if "Deserialize" in line: will match these strings anywhere in the line, including:

  • Comments: // Implements Serialize for Foo
  • String literals: "Serialize"
  • Compound identifiers: DeserializeOwned, CustomSerialize

This could inflate hasSerdeMention results. If precision is important, consider regex matching for derive attributes or trait bounds.

🎯 More precise matching with regex
+import re
+
 def _generate_source_lines(
   source_root: Path,
   query_dir: Path,
 ) -> Path:
   ...
+  serde_pattern = re.compile(r'\b(Serialize|Deserialize)\b')
   for rs_file in sorted(source_root.rglob("*.rs")):
     ...
     for lineno, line in enumerate(text.splitlines(), 1):
       stripped = line.lstrip()
-      if "Serialize" in line:
+      match = serde_pattern.search(line)
+      if match and "Serialize" in match.group(0):
         serde_rows.append(
           f'  file = "{rel}" and line = {lineno}'
           f' and trait = "Serialize"',
         )
-      if "Deserialize" in line:
+      if match and "Deserialize" in match.group(0):
         serde_rows.append(
           f'  file = "{rel}" and line = {lineno}'
           f' and trait = "Deserialize"',
         )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contrib/lint/lint_codeql.py` around lines 65 - 74, The substring checks using
if "Serialize" in line / if "Deserialize" in line produce false positives;
update the logic that populates serde_rows (and any hasSerdeMention usage) to
use regex whole-word/attribute matching instead: match derive attributes (e.g.,
a regex that finds
#[...derive(...Serialize...)]/#[...derive(...Deserialize...)]), impl/trait
occurrences as whole words (e.g., \bSerialize\b and \bDeserialize\b) and avoid
matching inside string literals/comments by focusing on attribute/impl/trait
patterns; apply these regexes where serde_rows is appended to ensure only real
derives/trait uses are captured.
contrib/lint/common.py (1)

39-46: 💤 Low value

Consider more robust workspace detection.

The substring check "[workspace]" in cargo.read_text(...) could theoretically match [workspace] in a comment or string literal. While unlikely in practice for Cargo.toml files, a more robust check would parse the TOML or use a regex to match the section header at line start.

🔍 More robust detection using regex
 def is_workspace_root(d: Path) -> bool:
   """Return True if *d* looks like a Cargo workspace root."""
+  import re
   cargo = d / "Cargo.toml"
-  return (
-    cargo.is_file()
-    and "[workspace]" in cargo.read_text(encoding="utf-8")
-    and (d / "pkgs").is_dir()
-  )
+  if not cargo.is_file() or not (d / "pkgs").is_dir():
+    return False
+  text = cargo.read_text(encoding="utf-8")
+  return bool(re.search(r'^\s*\[workspace\]', text, re.MULTILINE))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contrib/lint/common.py` around lines 39 - 46, The current is_workspace_root
function uses a substring check which can match inside comments or strings;
update it to robustly detect a TOML section header by reading the Cargo.toml and
using a multiline regex to match a line that starts with an optional whitespace
followed by exactly "[workspace]" (e.g. re.search(r'^\s*\[workspace\]\s*$',
content, re.MULTILINE)), keeping the existing checks for cargo.is_file() and (d
/ "pkgs").is_dir(); ensure you still read the file with encoding="utf-8" and
return the boolean result of the regex search.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/build_msrv.yml:
- Around line 51-58: The workflow restores the cargo registry with the "Restore
cargo registry" step (uses: actions/cache/restore@v5) in both the lint and build
jobs but never saves it back, so add a corresponding cache save step (uses:
actions/cache/save@v5) in each job after the job's dependency installation/build
steps; use the same path block (~/.cargo/registry and ~/.cargo/git) and the same
key (cargo-deps-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('Cargo.lock')
}}) and restore-keys to persist updates to the cache for future runs.

In `@CLAUDE.md`:
- Line 12: The CLAUDE.md "eager traits" guidance currently omits Default but the
codebase eagerly derives Default on several types (e.g. types::uint,
primitives::validation, primitives::script, primitives::block_header,
script::key_id, p2p_core::service_flags, num::compact, num::arith256); fix by
choosing one of two actions and applying it consistently: either (A) update
CLAUDE.md to explicitly include Default as an eagerly-derived trait and list any
intentional exceptions, or (B) remove the unnecessary #[derive(Default)] from
the noted types (or their structs/enums) so the docs and code match; ensure the
change references the specific types above and update the CLAUDE.md wording to
reflect the decided policy and any exceptions.

---

Nitpick comments:
In @.github/workflows/build_msrv.yml:
- Around line 21-24: The checkout steps using actions/checkout@v6 (the step with
name "Checkout" and any other actions/checkout@v6 occurrences) should explicitly
set persist-credentials: false under the with: block to avoid persisting
GITHUB_TOKEN in the workspace; update the with: block on the existing checkout
step (currently containing fetch-depth: 0) and any other checkout steps in the
file to include persist-credentials: false while preserving existing keys like
fetch-depth.

In `@contrib/lint/common.py`:
- Around line 39-46: The current is_workspace_root function uses a substring
check which can match inside comments or strings; update it to robustly detect a
TOML section header by reading the Cargo.toml and using a multiline regex to
match a line that starts with an optional whitespace followed by exactly
"[workspace]" (e.g. re.search(r'^\s*\[workspace\]\s*$', content, re.MULTILINE)),
keeping the existing checks for cargo.is_file() and (d / "pkgs").is_dir();
ensure you still read the file with encoding="utf-8" and return the boolean
result of the regex search.

In `@contrib/lint/lint_codeql.py`:
- Around line 65-74: The substring checks using if "Serialize" in line / if
"Deserialize" in line produce false positives; update the logic that populates
serde_rows (and any hasSerdeMention usage) to use regex whole-word/attribute
matching instead: match derive attributes (e.g., a regex that finds
#[...derive(...Serialize...)]/#[...derive(...Deserialize...)]), impl/trait
occurrences as whole words (e.g., \bSerialize\b and \bDeserialize\b) and avoid
matching inside string literals/comments by focusing on attribute/impl/trait
patterns; apply these regexes where serde_rows is appended to ensure only real
derives/trait uses are captured.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 36e7e2fb-8674-4113-a28c-8c4937614094

📥 Commits

Reviewing files that changed from the base of the PR and between 0238912 and ef17644.

⛔ Files ignored due to path filters (133)
  • pkgs/num/src/compact.rs is excluded by !**/*.rs
  • pkgs/num/src/hash.rs is excluded by !**/*.rs
  • pkgs/num/src/hash_encoding.rs is excluded by !**/*.rs
  • pkgs/num/src/lib.rs is excluded by !**/*.rs
  • pkgs/num/src/prelude.rs is excluded by !**/*.rs
  • pkgs/num/src/serialize.rs is excluded by !**/*.rs
  • pkgs/num/src/util.rs is excluded by !**/*.rs
  • pkgs/num/tests/arith.rs is excluded by !**/*.rs
  • pkgs/num/tests/hash.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/encode.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/error.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/lib.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/addr.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/cfcheckpt.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/cfheaders.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/cfilter.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/govobj.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/govobjvote.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/govsync.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/headers.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/headers2.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/inv.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/mnlistdiff.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/mod.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/ping.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/msg/version.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/prelude.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/primitives/command.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/primitives/compressed_header.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/primitives/governance.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/primitives/inventory.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/primitives/magic.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/primitives/mn_list.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/primitives/mod.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/primitives/net_addr.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/primitives/service_flags.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/primitives/short_id.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/primitives/user_agent.rs is excluded by !**/*.rs
  • pkgs/p2p_core/src/v2/mod.rs is excluded by !**/*.rs
  • pkgs/p2p_core/tests/addrv2.rs is excluded by !**/*.rs
  • pkgs/p2p_core/tests/mnlistdiff.rs is excluded by !**/*.rs
  • pkgs/params/src/lib.rs is excluded by !**/*.rs
  • pkgs/params/src/prelude.rs is excluded by !**/*.rs
  • pkgs/params/src/types.rs is excluded by !**/*.rs
  • pkgs/pkc/bench/main.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_chia/agg.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_chia/mod.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_chia/pk.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_chia/ser.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_chia/sig.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_chia/sk.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_chia/threshold.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_ietf/agg.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_ietf/mod.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_ietf/pk.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_ietf/sig.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_ietf/sk.rs is excluded by !**/*.rs
  • pkgs/pkc/src/bls_ietf/threshold.rs is excluded by !**/*.rs
  • pkgs/pkc/src/common/bls/mod.rs is excluded by !**/*.rs
  • pkgs/pkc/src/common/bls/threshold.rs is excluded by !**/*.rs
  • pkgs/pkc/src/k256/pk.rs is excluded by !**/*.rs
  • pkgs/pkc/src/k256/sig.rs is excluded by !**/*.rs
  • pkgs/pkc/src/k256/sk.rs is excluded by !**/*.rs
  • pkgs/pkc/src/lib.rs is excluded by !**/*.rs
  • pkgs/pkc/src/worker.rs is excluded by !**/*.rs
  • pkgs/pkc/tests/bls_chia_llmq.rs is excluded by !**/*.rs
  • pkgs/pkc/tests/bls_ietf_llmq.rs is excluded by !**/*.rs
  • pkgs/pow/src/bmw/simd.rs is excluded by !**/*.rs
  • pkgs/pow/src/cubehash/simd.rs is excluded by !**/*.rs
  • pkgs/pow/src/echo/simd.rs is excluded by !**/*.rs
  • pkgs/pow/src/groestl/mod.rs is excluded by !**/*.rs
  • pkgs/pow/src/groestl/simd.rs is excluded by !**/*.rs
  • pkgs/pow/src/jh/mod.rs is excluded by !**/*.rs
  • pkgs/pow/src/jh/simd.rs is excluded by !**/*.rs
  • pkgs/pow/src/keccak/mod.rs is excluded by !**/*.rs
  • pkgs/pow/src/lib.rs is excluded by !**/*.rs
  • pkgs/pow/src/luffa/consts.rs is excluded by !**/*.rs
  • pkgs/pow/src/luffa/mod.rs is excluded by !**/*.rs
  • pkgs/pow/src/luffa/simd.rs is excluded by !**/*.rs
  • pkgs/pow/src/prelude.rs is excluded by !**/*.rs
  • pkgs/pow/src/shavite/simd.rs is excluded by !**/*.rs
  • pkgs/pow/src/simd_hash/simd.rs is excluded by !**/*.rs
  • pkgs/pow/src/skein/simd.rs is excluded by !**/*.rs
  • pkgs/pow/src/util/aes/mod.rs is excluded by !**/*.rs
  • pkgs/pow/src/worker.rs is excluded by !**/*.rs
  • pkgs/pow/tests/blake.rs is excluded by !**/*.rs
  • pkgs/pow/tests/bmw.rs is excluded by !**/*.rs
  • pkgs/pow/tests/common/mod.rs is excluded by !**/*.rs
  • pkgs/pow/tests/cubehash.rs is excluded by !**/*.rs
  • pkgs/pow/tests/echo.rs is excluded by !**/*.rs
  • pkgs/pow/tests/groestl.rs is excluded by !**/*.rs
  • pkgs/pow/tests/jh.rs is excluded by !**/*.rs
  • pkgs/pow/tests/keccak.rs is excluded by !**/*.rs
  • pkgs/pow/tests/luffa.rs is excluded by !**/*.rs
  • pkgs/pow/tests/shavite.rs is excluded by !**/*.rs
  • pkgs/pow/tests/simd_hash.rs is excluded by !**/*.rs
  • pkgs/pow/tests/skein.rs is excluded by !**/*.rs
  • pkgs/primitives/src/block.rs is excluded by !**/*.rs
  • pkgs/primitives/src/block_header.rs is excluded by !**/*.rs
  • pkgs/primitives/src/codec.rs is excluded by !**/*.rs
  • pkgs/primitives/src/error.rs is excluded by !**/*.rs
  • pkgs/primitives/src/gov.rs is excluded by !**/*.rs
  • pkgs/primitives/src/lib.rs is excluded by !**/*.rs
  • pkgs/primitives/src/outpoint.rs is excluded by !**/*.rs
  • pkgs/primitives/src/payload/assetlock.rs is excluded by !**/*.rs
  • pkgs/primitives/src/payload/assetunlock.rs is excluded by !**/*.rs
  • pkgs/primitives/src/payload/cbtx.rs is excluded by !**/*.rs
  • pkgs/primitives/src/payload/mnhftx.rs is excluded by !**/*.rs
  • pkgs/primitives/src/payload/mod.rs is excluded by !**/*.rs
  • pkgs/primitives/src/payload/proregtx.rs is excluded by !**/*.rs
  • pkgs/primitives/src/payload/proupregtx.rs is excluded by !**/*.rs
  • pkgs/primitives/src/payload/prouprevtx.rs is excluded by !**/*.rs
  • pkgs/primitives/src/payload/proupservtx.rs is excluded by !**/*.rs
  • pkgs/primitives/src/payload/quorum.rs is excluded by !**/*.rs
  • pkgs/primitives/src/prelude.rs is excluded by !**/*.rs
  • pkgs/primitives/src/script.rs is excluded by !**/*.rs
  • pkgs/primitives/src/serialize.rs is excluded by !**/*.rs
  • pkgs/primitives/src/support.rs is excluded by !**/*.rs
  • pkgs/primitives/src/transaction.rs is excluded by !**/*.rs
  • pkgs/primitives/src/tx_in.rs is excluded by !**/*.rs
  • pkgs/primitives/src/tx_out.rs is excluded by !**/*.rs
  • pkgs/primitives/src/tx_types.rs is excluded by !**/*.rs
  • pkgs/primitives/src/validation.rs is excluded by !**/*.rs
  • pkgs/primitives/src/wire.rs is excluded by !**/*.rs
  • pkgs/primitives/tests/util/mod.rs is excluded by !**/*.rs
  • pkgs/script/src/key_id.rs is excluded by !**/*.rs
  • pkgs/script/src/lib.rs is excluded by !**/*.rs
  • pkgs/script/src/opcode.rs is excluded by !**/*.rs
  • pkgs/script/src/prelude.rs is excluded by !**/*.rs
  • pkgs/types/src/hex.rs is excluded by !**/*.rs
  • pkgs/types/src/lib.rs is excluded by !**/*.rs
  • pkgs/types/src/prelude.rs is excluded by !**/*.rs
  • pkgs/types/src/uint.rs is excluded by !**/*.rs
📒 Files selected for processing (29)
  • .github/workflows/build_msrv.yml
  • .github/workflows/build_stable.yml
  • .github/workflows/lint_all.yml
  • .github/workflows/pr_comment.yml
  • .github/workflows/pr_tag.yml
  • CLAUDE.md
  • contrib/codeql/.gitignore
  • contrib/codeql/attrib.ql
  • contrib/codeql/codeql-pack.lock.yml
  • contrib/codeql/import.ql
  • contrib/codeql/lib/files.qll
  • contrib/codeql/lib/filters.qll
  • contrib/codeql/lib/fmt.qll
  • contrib/codeql/lib/imports.qll
  • contrib/codeql/lib/policy.qll
  • contrib/codeql/lib/traits.qll
  • contrib/codeql/qlpack.yml
  • contrib/codeql/secret.ql
  • contrib/lint/all_lint.py
  • contrib/lint/common.py
  • contrib/lint/lint_codeql.py
  • contrib/lint/lint_javascript.py
  • contrib/lint/lint_python.py
  • contrib/lint/lint_semgrep.py
  • contrib/semgrep/prelude.yml
  • contrib/semgrep/serde.yml
  • docs/guide_rust.md
  • pkgs/primitives/Cargo.toml
  • pyproject.toml
💤 Files with no reviewable changes (1)
  • .github/workflows/lint_all.yml

Comment thread .github/workflows/build_msrv.yml Outdated
Comment on lines +51 to +58
- name: Restore cargo registry
uses: actions/cache/restore@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
key: cargo-deps-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('Cargo.lock') }}
restore-keys: cargo-deps-${{ runner.os }}-${{ runner.arch }}-

@coderabbitai coderabbitai Bot Jun 5, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Cargo registry cache is restored but never saved.

Both the lint and build jobs restore the cargo registry cache (lines 51-58 and 98-105), but neither job saves it. This means:

  • The workflow depends on other workflows (like build_stable.yml) to populate the cache
  • If this workflow runs in isolation (e.g., a develop branch push), the cache won't be updated when Cargo.lock changes
  • Cache misses and stale dependencies may degrade performance over time
💾 Add cache save steps

Add a save step to the lint job after line 70:

       - name: Run linters
         run: python3 contrib/lint/all_lint.py
 
+      - name: Save cargo registry
+        if: always()
+        uses: actions/cache/save@v5
+        with:
+          path: |
+            ~/.cargo/registry
+            ~/.cargo/git
+          key: cargo-deps-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('Cargo.lock') }}
+
       - name: Save CodeQL caches

And add a save step to the build job after line 111:

       - name: Test workspace
         run: cargo test --workspace --features full,_internal
+
+      - name: Save cargo registry
+        if: always()
+        uses: actions/cache/save@v5
+        with:
+          path: |
+            ~/.cargo/registry
+            ~/.cargo/git
+          key: cargo-deps-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('Cargo.lock') }}

Also applies to: 98-105

🧰 Tools
🪛 zizmor (1.25.2)

[error] 52-52: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build_msrv.yml around lines 51 - 58, The workflow restores
the cargo registry with the "Restore cargo registry" step (uses:
actions/cache/restore@v5) in both the lint and build jobs but never saves it
back, so add a corresponding cache save step (uses: actions/cache/save@v5) in
each job after the job's dependency installation/build steps; use the same path
block (~/.cargo/registry and ~/.cargo/git) and the same key (cargo-deps-${{
runner.os }}-${{ runner.arch }}-${{ hashFiles('Cargo.lock') }}) and restore-keys
to persist updates to the cache for future runs.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The registry is source-based and improvements have been force pushed, we did away with the unnecessary keying.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
cat .github/workflows/build_msrv.yml

Length of output: 3122



@kwvg, understood — I can see the simplified key (cargo-deps-${{ hashFiles('Cargo.lock') }} without OS/arch segments) in the updated file. The design makes sense: the cargo cache is populated by another workflow and consumed here, so a separate save step isn't needed. Thanks for the clarification.


✏️ Learnings added
Learnt from: kwvg
Repo: dashpay/base-sdk PR: 5
File: .github/workflows/build_msrv.yml:0-0
Timestamp: 2026-06-06T06:09:05.124Z
Learning: In the `dashpay/base-sdk` repository, the cargo registry cache in `.github/workflows/build_msrv.yml` is intentionally restore-only (`actions/cache/restorev5`). The cache is populated by another workflow (e.g., `build_stable.yml`) and only consumed in this workflow. The cache key deliberately omits `runner.os` and `runner.arch` segments as they were deemed unnecessary for this setup.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread CLAUDE.md
`SCREAMING_SNAKE_CASE` for constants. Acronyms as words (`TxId` not `TXID`). Getters omit `get_` prefix.
- **Type safety**: newtypes over primitives when semantics differ, enums over booleans, make invalid states
unrepresentable. Derive `Clone`, `Debug`, `PartialEq`, `Eq`, `Hash`, `Default` eagerly.
unrepresentable. Derive `Clone`, `Debug`, `PartialEq`, `Eq`, `Hash` eagerly.

@coderabbitai coderabbitai Bot Jun 5, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Find all derive attributes that include Default

rg -nP --type=rust 'derive\([^)]*\bDefault\b[^)]*\)' pkgs/

Repository: dashpay/base-sdk

Length of output: 886


Fix mismatch between CLAUDE.md “eager traits” guidance and the repo’s Default derives

The current guideline snippet shows eagerly deriving Clone, Debug, PartialEq, Eq, Hash (no Default), but there are many existing Default derives across pkgs/:

  • pkgs/types/src/uint.rs:34
  • pkgs/primitives/src/validation.rs:59
  • pkgs/primitives/src/script.rs:19
  • pkgs/primitives/src/block_header.rs:17
  • pkgs/script/src/key_id.rs:14
  • pkgs/p2p_core/src/primitives/service_flags.rs:15
  • pkgs/num/src/compact.rs:16,20
  • pkgs/num/src/arith256.rs:22

Align the intended policy: either remove Default derives where appropriate in this PR/follow-up, or update CLAUDE.md to reflect whether Default is meant to be eagerly derived (and list any explicit exceptions).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CLAUDE.md` at line 12, The CLAUDE.md "eager traits" guidance currently omits
Default but the codebase eagerly derives Default on several types (e.g.
types::uint, primitives::validation, primitives::script,
primitives::block_header, script::key_id, p2p_core::service_flags, num::compact,
num::arith256); fix by choosing one of two actions and applying it consistently:
either (A) update CLAUDE.md to explicitly include Default as an eagerly-derived
trait and list any intentional exceptions, or (B) remove the unnecessary
#[derive(Default)] from the noted types (or their structs/enums) so the docs and
code match; ensure the change references the specific types above and update the
CLAUDE.md wording to reflect the decided policy and any exceptions.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We don't prohibit deriving Default, we just don't enforce it in linting.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@kwvg, understood — Default derivation is permitted but not mandated by the linter, so the CLAUDE.md guidance correctly reflects only what is enforced. I've noted this for future reviews.


✏️ Learnings added
Learnt from: kwvg
Repo: dashpay/base-sdk PR: 5
File: CLAUDE.md:12-12
Timestamp: 2026-06-06T06:09:25.351Z
Learning: In `dashpay/base-sdk`, deriving `Default` on types is allowed but not enforced by linting. The "eager derives" list in `CLAUDE.md` (Clone, Debug, PartialEq, Eq, Hash) reflects only what the linter *requires*, not what is *prohibited*. Types may still derive `Default` at the developer's discretion without violating project policy.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@kwvg kwvg marked this pull request as ready for review June 6, 2026 06:07
@kwvg kwvg changed the title sdk%lint: introduce CodeQL and semgrep linters, add shim, derivation, disambiguation rules, resolve violations, add common helper for lint infra sdk%lint: introduce CodeQL and semgrep linters, add shim, derivation, disambiguation rules, resolve violations, add common helper for lint infra Jun 6, 2026
@kwvg kwvg merged commit 4e93394 into dashpay:develop Jun 6, 2026
37 checks passed
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.

1 participant