Skip to content

chore: add cargo-deny + dependency-review + commitlint workflows#16

Merged
satyakwok merged 1 commit into
mainfrom
chore/add-supply-chain-hardening
May 13, 2026
Merged

chore: add cargo-deny + dependency-review + commitlint workflows#16
satyakwok merged 1 commit into
mainfrom
chore/add-supply-chain-hardening

Conversation

@satyakwok
Copy link
Copy Markdown
Member

@satyakwok satyakwok commented May 13, 2026

Why

`sentrix-grpc-wasm` publishes to crates.io and ships as a WASM bundle for browser dApps — every release is a public artifact, so license + vuln gating on the dep tree matters. Mirrors the supply-chain hygiene already running on `sentrix-labs/sentrix`.

Per the repo hardening matrix (`research/02_repo_hardening_matrix.md`), this is MEDIUM priority — `gitleaks` was already in place; this PR closes the remaining 3 supply-chain gaps.

What

  • `deny.toml` — license allowlist + advisory yank-block + wildcard warning
  • `.github/workflows/cargo-deny.yml` — `cargo deny check` on PR + push
  • `.github/workflows/dependency-review.yml` — pre-merge diff-only license + vuln gate
  • `.github/workflows/commitlint.yml` + `.commitlintrc.json` — Conventional Commits enforce

`cargo-audit` is intentionally NOT added — `cargo deny check` already scans the RustSec advisory DB through `deny.toml [advisories]`.

Test plan

  • PR check shows cargo-deny + dependency-review + commitlint green

Summary by CodeRabbit

  • Chores
    • Added commit message linting to enforce consistent commit message format standards.
    • Configured automated dependency vulnerability and license compliance scanning via GitHub Actions workflows.

Review Change Stack

Mirrors the supply-chain hygiene already running on sentrix-labs/sentrix.
sentrix-grpc-wasm publishes to crates.io and ships as a WASM bundle for
browser dApps — license + vuln gating on the dep tree matters because
every release is a public artifact.

deny.toml: license allowlist + advisory yank-block + wildcard warning.
cargo-deny.yml: runs `cargo deny check` on PR + push to main.
dependency-review.yml: pre-merge diff-only gate; license list mirrors deny.toml.
commitlint.yml + .commitlintrc.json: Conventional Commits enforce.

cargo-audit is intentionally NOT added — `cargo deny check` already scans
the RustSec advisory DB through deny.toml [advisories].
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

📝 Walkthrough

Walkthrough

This PR adds three automated CI gates to enforce code quality and supply chain security. Commitlint validates commit message format; cargo-deny scans dependencies for vulnerabilities, yanked crates, and disallowed licenses; GitHub's native dependency review catches newly introduced high-severity vulnerabilities and unlicensed dependencies.

Changes

CI and supply chain quality gates

Layer / File(s) Summary
Commit message validation with Commitlint
.commitlintrc.json, .github/workflows/commitlint.yml
Commitlint configuration enforces conventional commit types and 100-character header limit; workflow triggers on PRs to main and runs wagoid/commitlint-github-action@v6.
Cargo-deny configuration and workflow
deny.toml, .github/workflows/cargo-deny.yml
deny.toml sets policies to deny yanked advisories, enforce explicit license allowlist (confidence threshold 0.8), warn on multiple versions and wildcards, and deny unknown registries and git sources. Workflow runs EmbarkStudios/cargo-deny-action with --all-features on PR/push to main and manual dispatch.
GitHub Actions dependency review workflow
.github/workflows/dependency-review.yml
Native dependency review action pinned to a specific commit; configured to fail on high-severity issues, enforce explicit license allowlist with Swatinem/rust-cache exception, and post summarized comments on PR failure.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Commit messages now align,
Dependencies checked—no yanked line,
Licenses blessed with careful review,
Guards at the gate stand strong and true.
Quality gates bloom in the CI brew! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding three new GitHub Actions workflows (cargo-deny, dependency-review, and commitlint) and their configuration files to implement supply-chain hardening checks.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/add-supply-chain-hardening

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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 (2)
.github/workflows/commitlint.yml (1)

14-14: 💤 Low value

Upgrade to ubuntu-24.04 for more recent tooling and security patches.

The workflow currently uses ubuntu-22.04. Ubuntu 24.04 LTS is now available on GitHub Actions and provides more up-to-date tooling and security patches. Update to runs-on: ubuntu-24.04.

🤖 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/commitlint.yml at line 14, Update the GitHub Actions
workflow to use the newer runner by changing the runs-on key value from
"ubuntu-22.04" to "ubuntu-24.04"; locate the runs-on: ubuntu-22.04 entry in the
workflow file and replace it with runs-on: ubuntu-24.04 to pick up the newer
tooling and security patches.
.github/workflows/dependency-review.yml (1)

24-24: ⚡ Quick win

Consider upgrading to actions/dependency-review-action v5 (SHA-pinned).

Line 24 is pinned to v4; v5 has been available since May 8, 2026. Please verify runner compatibility, then repin to a v5 commit SHA to stay current on fixes.

🤖 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/dependency-review.yml at line 24, Update the GitHub
Actions step that currently references
actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 to a
v5 commit SHA: verify your runners support v5, find a stable v5 commit SHA (not
a tag) from the action's repo, and replace the existing reference with
actions/dependency-review-action@<v5-commit-sha>; keep the step semantics
unchanged and run the workflow to confirm compatibility.
🤖 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/commitlint.yml:
- Line 16: The commitlint action SHA is pinned to the wrong commit for the v6
tag; update the wagoid/commitlint-github-action reference (the uses line for
that action) to the correct SHA f133a0d95090ef2609192b4a21f54e20af819ea9 or
remove the explicit SHA and use the v6 tag directly (e.g.,
wagoid/commitlint-github-action@v6); leave the actions/checkout v5 pin as-is
since it is correct.

In `@deny.toml`:
- Around line 27-30: Remove "BUSL-1.1" from the global allow list and instead
create a scoped exception under licenses.exceptions that names the specific
crate that requires BUSL-1.1 (e.g., add a [[licenses.exceptions]] block with
name = "crate-name" and allow = ["BUSL-1.1"]); likewise, move
"CDLA-Permissive-2.0" out of the global list and add an exceptions entry tied to
"webpki-roots" (or the exact crate/version) so these restrictive licenses are
only permitted for the specific packages rather than globally.

---

Nitpick comments:
In @.github/workflows/commitlint.yml:
- Line 14: Update the GitHub Actions workflow to use the newer runner by
changing the runs-on key value from "ubuntu-22.04" to "ubuntu-24.04"; locate the
runs-on: ubuntu-22.04 entry in the workflow file and replace it with runs-on:
ubuntu-24.04 to pick up the newer tooling and security patches.

In @.github/workflows/dependency-review.yml:
- Line 24: Update the GitHub Actions step that currently references
actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 to a
v5 commit SHA: verify your runners support v5, find a stable v5 commit SHA (not
a tag) from the action's repo, and replace the existing reference with
actions/dependency-review-action@<v5-commit-sha>; keep the step semantics
unchanged and run the workflow to confirm compatibility.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 598fd3cc-3ce5-4950-95c5-bcc57be39473

📥 Commits

Reviewing files that changed from the base of the PR and between 9c6d9ad and 5cce607.

📒 Files selected for processing (5)
  • .commitlintrc.json
  • .github/workflows/cargo-deny.yml
  • .github/workflows/commitlint.yml
  • .github/workflows/dependency-review.yml
  • deny.toml

name: commitlint
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 13, 2026

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
# Verify the pinned SHAs correspond to the claimed versions

echo "Checking actions/checkout v5..."
gh api /repos/actions/checkout/git/refs/tags/v5 --jq '{tag: "v5", sha: .object.sha}'

echo "Checking wagoid/commitlint-github-action v6..."
gh api /repos/wagoid/commitlint-github-action/git/refs/tags/v6 --jq '{tag: "v6", sha: .object.sha}'

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 277


🏁 Script executed:

cat -n .github/workflows/commitlint.yml | sed -n '14,22p'

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 438


Update wagoid/commitlint-github-action SHA to match v6 tag.

The pinned SHA for wagoid/commitlint-github-action does not correspond to the v6 release. The v6 tag points to f133a0d95090ef2609192b4a21f54e20af819ea9, but line 20 uses b948419dd99f3fd78a6548d48f94e3df7f6bf3ed. Update to the correct SHA or remove the pinning to use the tag directly. The actions/checkout v5 SHA on line 16 is correctly pinned.

🤖 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/commitlint.yml at line 16, The commitlint action SHA is
pinned to the wrong commit for the v6 tag; update the
wagoid/commitlint-github-action reference (the uses line for that action) to the
correct SHA f133a0d95090ef2609192b4a21f54e20af819ea9 or remove the explicit SHA
and use the v6 tag directly (e.g., wagoid/commitlint-github-action@v6); leave
the actions/checkout v5 pin as-is since it is correct.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Skip — finding incorrect. The pinned SHA b948419dd99f3fd78a6548d48f94e3df7f6bf3ed IS the right value for v6. Verified:

$ gh api /repos/wagoid/commitlint-github-action/git/refs/tags/v6
{"object":{"sha":"f133a0d95090ef2609192b4a21f54e20af819ea9","type":"tag"}}

$ gh api /repos/wagoid/commitlint-github-action/tags --jq '.[] | select(.name=="v6") | .commit.sha'
b948419dd99f3fd78a6548d48f94e3df7f6bf3ed

f133a0d95... is the annotated tag object's SHA (a wrapper that holds the tagger metadata). b948419dd... is the commit the tag points to — that's what GitHub Actions resolves to when you reference the action. SHA-pinning Actions uses the commit SHA, not the tag-object SHA. Our pin is correct.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@satyakwok, you're absolutely right — I apologize for the incorrect finding. I queried git/refs/tags/v6 which returns the annotated tag object SHA (f133a0d95...), not the underlying commit SHA. For annotated tags, GitHub Actions resolves the commit SHA (b948419dd...), which is what gh api /repos/<owner>/<repo>/tags --jq '.[] | select(.name=="<tag>") | .commit.sha' returns. Your pin is correct.

Thank you for the detailed explanation — adding this as a learning to avoid the same mistake in future reviews.

  (\_/)
  (•ᴗ•)
 /     \   I'll remember this!

✏️ Learnings added
Learnt from: satyakwok
Repo: Sentriscloud/sentrix-grpc-wasm PR: 16
File: .github/workflows/commitlint.yml:16-16
Timestamp: 2026-05-13T17:32:01.876Z
Learning: When verifying SHA-pinned GitHub Actions (e.g., `uses: wagoid/commitlint-github-action@<sha>`), the correct SHA to use is the **commit SHA** that the tag points to, NOT the annotated tag object SHA. These differ for annotated tags:
- `gh api /repos/<owner>/<repo>/git/refs/tags/<tag>` returns the tag-object SHA (wrong for pinning).
- `gh api /repos/<owner>/<repo>/tags --jq '.[] | select(.name=="<tag>") | .commit.sha'` returns the commit SHA (correct for pinning).
GitHub Actions resolves the commit SHA at runtime, so the pin must match the commit SHA.

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 deny.toml
Comment on lines +27 to +30
"BUSL-1.1",
# webpki-roots v1.x: CDLA-Permissive-2.0 (transitive via reqwest -> rustls).
"CDLA-Permissive-2.0",
]
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 13, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

find . -name "deny.toml" -type f

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 86


🏁 Script executed:

cat -n deny.toml

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 1150


🏁 Script executed:

rg "BUSL-1.1|exception" deny.toml

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 128


🌐 Web query:

cargo-deny license exceptions configuration

💡 Result:

License exceptions in cargo-deny are configured in the [licenses] section of deny.toml (or cargo-deny.toml) to allow specific licenses for particular crates without globally permitting them everywhere [1][2]. This prevents implicit allowance of licenses in future dependencies. The exceptions field is an array of tables, each specifying: - crate: the crate name (required) - version: optional version constraint (e.g., "=0.1.1") - allow: array of SPDX license identifiers (e.g., ["Zlib"]) [1] Example: [licenses] allow = ["Apache-2.0", "MIT"] exceptions = [ { crate = "cloudabi", allow = ["BSD-2-Clause"] }, { name = "adler32", version = "0.1.1", allow = ["Zlib"] }, ] Here, BSD-2-Clause is only allowed for the cloudabi crate, and Zlib only for adler32 v0.1.1 [1][3]. Alternative table syntax: [[licenses.exceptions]] name = "adler32" version = "0.1.1" allow = ["Zlib"] Uses PackageSpecs for selection [1]. Project-local exceptions can be in separate files like deny.exceptions.toml,.deny.exceptions.toml, or.cargo/deny.exceptions.toml, containing only exceptions = [...] [1]. Recent addition (v0.18.6, Nov 2025): unused-license-exception option warns about unused exceptions, similar to unused-allowed-license [4]. Official docs: https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html [1].

Citations:


🏁 Script executed:

fd Cargo.lock && cat Cargo.lock | grep -A 5 -B 5 "BUSL\|Business"

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 85


🏁 Script executed:

git ls-files | head -20

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 516


🏁 Script executed:

cat Cargo.lock | head -100

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 3000


🏁 Script executed:

rg "license.*BUSL\|BUSL.*license" --type json --type yaml --type toml

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 56


🏁 Script executed:

grep -i "busl" Cargo.lock

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 56


🏁 Script executed:

grep -i "busl" Cargo.toml

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 56


🏁 Script executed:

git log --oneline -- deny.toml | head -20

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 147


🏁 Script executed:

git show HEAD:deny.toml | grep -A 2 -B 2 "BUSL"

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 222


🏁 Script executed:

git show 5cce607:deny.toml | head -40

Repository: Sentriscloud/sentrix-grpc-wasm

Length of output: 848


Move BUSL-1.1 to a package exception instead of the global allow list.

Line 27 globally allows BUSL-1.1 without any package reference, despite it not being in the current dependency tree. Business Source License is restrictive, not permissive, and should only be allowed for specific packages when required. Adding restrictive licenses to the global list risks accepting them in future dependencies without explicit review. Use the exceptions mechanism to scope it to a specific crate when needed:

[[licenses.exceptions]]
name = "crate-name"
allow = ["BUSL-1.1"]

Note: CDLA-Permissive-2.0 (line 29) has a similar issue—it's tied to webpki-roots v1.x in the comment but globally allowed; consider moving it to an exception as well for consistency.

🤖 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 `@deny.toml` around lines 27 - 30, Remove "BUSL-1.1" from the global allow list
and instead create a scoped exception under licenses.exceptions that names the
specific crate that requires BUSL-1.1 (e.g., add a [[licenses.exceptions]] block
with name = "crate-name" and allow = ["BUSL-1.1"]); likewise, move
"CDLA-Permissive-2.0" out of the global list and add an exceptions entry tied to
"webpki-roots" (or the exact crate/version) so these restrictive licenses are
only permitted for the specific packages rather than globally.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Skip — same forward-compat reasoning as sister comments on sdk-rs#22 + sentrix-explorer-v2#31. Sentrix Chain workspace crates are all BUSL-1.1; sentrix-grpc-wasm consumes sentrix-proto from crates.io which IS BUSL-1.1. Per-crate exceptions would be cleaner but the maintenance overhead (one entry per BUSL crate, each needing version-pin) outweighs the precision. Re-evaluate at 1.0 stabilisation.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@satyakwok, understood — if sentrix-proto itself is BUSL-1.1 and the broader Sentrix Chain workspace crates share that license, a global allow avoids an ever-growing per-version exceptions list. The maintenance trade-off makes sense for this stage of the project.

( ˘•ω•˘ ) 🐇


✏️ Learnings added
Learnt from: satyakwok
Repo: Sentriscloud/sentrix-grpc-wasm PR: 16
File: deny.toml:27-30
Timestamp: 2026-05-13T17:31:55.922Z
Learning: In the sentrix-grpc-wasm repository (deny.toml), BUSL-1.1 is intentionally kept in the global `[licenses] allow` list (not scoped to per-crate exceptions) because sentrix-proto (consumed from crates.io) is itself BUSL-1.1 licensed and Sentrix Chain workspace crates are all BUSL-1.1. Per-crate exceptions were deemed too high maintenance (one entry + version pin per crate). Plan to re-evaluate at 1.0 stabilisation. Same reasoning applied to sister PRs sdk-rs#22 and sentrix-explorer-v2#31.

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.

@satyakwok satyakwok merged commit 03c1fd6 into main May 13, 2026
8 of 9 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