Skip to content

sdk%feat(doc): introduce Zensical-based documentation site, WASM-based demos, GitHub Pages workflow#10

Merged
kwvg merged 16 commits into
dashpay:developfrom
kwvg:wasm
Jun 18, 2026
Merged

sdk%feat(doc): introduce Zensical-based documentation site, WASM-based demos, GitHub Pages workflow#10
kwvg merged 16 commits into
dashpay:developfrom
kwvg:wasm

Conversation

@kwvg

@kwvg kwvg commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Motivation

Base SDK is built to run in resource-constrained environments with fewer platform assumptions, till now, the benefits have been largely theoretical. This pull request is part of a series to start building web-ready documentation with examples. As we target no_std + alloc, WASM support is trivial, allowing us to write interactive demos building on the same foundations used for native applications.

Future pull requests will document the protocol and the SDK's intended usage patterns as part of a more traditional series but this pull request for now sets up the infrastructure to allow these future contributions (mostly likely after the API shape of the SDK is more clear).

Additional Information

Main Page Samples landing page
Genesis Solver demo Object Parser demo
  • f64::round() is not available in core (see rust-lang/rust#137578), causing compile failures for wasm32-unknown-unknown.

    To remedy this, libm is pulled in as the community-standard no_std replacement (source) and the shim in prelude.rs dispatches to f64::round() when std is available.

  • CodeQL's fileCfgLines regex captured paths relative to pkgs/ but sourceLineContent returns paths relative to root after multi-directory expansion, causing silent mismatches. The regex was updated to align the two.

  • Shared utilities introduced in base-sdk#5 are located in contrib/lint/common.py and are inaccessible to code outside the lint directory. As the docs builder has overlapping needs, it has been moved to contrib.py (without the executable bit, just like __init__.py) with a symlink left in contrib/lint/ to allowing existing lint scripts to run modified.

  • The published docs are built using Zensical (a fork of MkDocs) with additional preprocessing, minification and build steps for WASM-enabled demos. It was chosen as Zensical provides relatively modern design sensibilities OOTB, extensibility that suits our needs and allowed us to maintain our documentation in Markdown, so it can be rendered on GitHub.

    • To that effect, pre-processing steps were added as Zensical does not natively support Github Flavoured Markdown (GFM). This meant warnings/errors/notes either had to be written as MkDocs admonitions or as GFM alerts. As admonitions are not rendered outside the MkDocs ecosystem, alerts were used instead and the pre-processing step does the relevant transformations, keeping our markdown clean.
  • The WASM sample crates live in a separate workspace (contrib/samples) rather than as members of the root workspace to keep WASM-specific dependencies (e.g. wasm-bindgen) out of the dependency tree.

    • WASM-generated glue code in pkg/ directories is excluded from JS minification because rjsmin can corrupt the wasm-bindgen output, which relies on specific string patterns for module instantiation.

Breaking Changes

None expected.

How Has This Been Tested?

./contrib/lint_all.py
./contrib/build_docs.py preview
cargo test --features full,_internal

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 15, 2026
@kwvg kwvg self-assigned this Jun 15, 2026
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds two interactive WASM browser samples (parser and solver) under a new contrib/samples Cargo workspace, introduces a Zensical-based documentation site with a GitHub Pages deploy workflow, promotes shared tooling utilities from contrib/lint/common.py to contrib/common.py, adds a no-std f64::round shim to pkgs/primitives, and expands lint tooling (CodeQL, semgrep, ESLint, new Markdown and Rust format checkers) to cover the new samples workspace.

Changes

WASM Samples, Documentation Site, and Tooling

Layer / File(s) Summary
no-std f64::round shim in primitives
pkgs/primitives/Cargo.toml, pkgs/primitives/src/prelude.rs, pkgs/primitives/src/serialize.rs
Adds cfg-if and libm dependencies, introduces a pub(crate) round() shim that delegates to f64::round() under std or libm::round otherwise, and updates amount deserialization to use it.
Promote shared contrib utilities
contrib/common.py, contrib/__init__.py, contrib/lint/common.py, contrib/lint_all.py, pyproject.toml
Moves RETCODE_* constants and all workspace/binary/resource helpers out of contrib/lint/common.py into a new top-level contrib/common.py; stubs the old file; fixes lint_all.py path resolution; registers contrib and contrib.zen packages and expands dev dependencies in pyproject.toml.
Parser WASM crate and browser UI
contrib/samples/Cargo.toml, contrib/samples/common.css, contrib/samples/parser/Cargo.toml, contrib/samples/parser/parser.rs, contrib/samples/parser/index.js, contrib/samples/parser/style.css
Defines the contrib/samples Cargo workspace; adds dash-sample-parser (cdylib, no_std) with parse_block_hex/parse_tx_hex WASM exports, JSON enrichment via enrich_tx/enrich_block, and an envelope response; provides the browser index.js (WASM init, buildTree DOM renderer) and shared/local CSS.
Solver WASM crate and parallel Web Worker UI
contrib/samples/solver/Cargo.toml, contrib/samples/solver/solver.rs, contrib/samples/solver/worker.js, contrib/samples/solver/index.js, contrib/samples/solver/style.css
Adds dash-sample-solver crate with merkle_root and scanhash WASM exports (ScanResult, coinbase construction, compact-target nonce loop); worker.js runs scanhash in batches posting progress/ok/done; index.js partitions nonce space across workers, applies a grace timeout, and displays solve rate and hash match.
Zensical documentation site infrastructure
zensical.toml, contrib/zen/__init__.py, contrib/build_docs.py, docs/zen/style.css, docs/README.md
Introduces zensical.toml (site config, navigation, mermaid fences), contrib/zen Markdown extension (GfmAlertsPreprocessor), contrib/build_docs.py CLI (build/preview verbs: wasm-pack compilation, zensical site gen, artifact copying, Pygments CSS, JS minification, HTTP preview server), and docs site CSS overrides.
Documentation content pages
docs/zen/index.md, docs/zen/samples/..., docs/guide_rust.md, README.md, CLAUDE.md
Adds SDK overview, versioning/policy, and samples index/parser/solver documentation pages; reformats guide_rust.md admonitions and wrapping; updates README.md features table, Mermaid diagram, and pyml comment annotations.
Lint tooling expanded to contrib/samples
contrib/lint/lint_rust.py, contrib/lint/lint_markdown.py, contrib/lint/lint_javascript.py, contrib/lint/lint_semgrep.py, contrib/lint/lint_codeql.py, contrib/codeql/..., contrib/js/eslint.config.mjs
Adds lint_rust.py (cargo fmt check for both workspaces) and lint_markdown.py (pymarkdownlnt wrapper); expands ESLint to cover contrib/samples with ES module globals; expands semgrep and CodeQL source scanning to contrib/samples; updates CodeQL to use --build-mode=none with codeql-config.yml and adds preludeExcludeCrate() policy for the sample crates.
CI workflow updates
.github/workflows/build_msrv.yml, .github/workflows/build_nightly.yml, .github/workflows/build_stable.yml, .github/workflows/pages.yml, .gitignore
Updates cargo registry cache keys to hash both lockfiles across all three existing workflows; adds rustfmt component and corrects lint script path in MSRV workflow; replaces inline cargo fmt with python lint_rust.py in nightly; introduces pages.yml (build + deploy jobs for GitHub Pages); adds public/ and *.wasm to .gitignore.

Sequence Diagrams

sequenceDiagram
  participant Browser as Browser (index.js)
  participant Worker as worker.js (×N Web Workers)
  participant SolverWASM as demo_solver.wasm
  participant ParserWASM as demo_parser.wasm

  rect rgba(100, 149, 237, 0.5)
    note over Browser,ParserWASM: Object Parser sample
    Browser->>ParserWASM: init() — load module
    ParserWASM-->>Browser: ready
    Browser->>ParserWASM: parse_block_hex(hex) or parse_tx_hex(hex)
    ParserWASM-->>Browser: envelope JSON {data, warnings}
    Browser->>Browser: buildTree() — render expandable DOM tree
  end

  rect rgba(144, 238, 144, 0.5)
    note over Browser,SolverWASM: Genesis Solver sample
    Browser->>SolverWASM: init() — load module
    SolverWASM-->>Browser: ready, load preset
    Browser->>SolverWASM: merkle_root(scriptSig, scriptPubkey, amount)
    SolverWASM-->>Browser: merkle root string
    Browser->>Worker: postMessage({header fields, nonceStart, nonceCount})
    Worker->>SolverWASM: scanhash(batch)
    loop per batch
      SolverWASM-->>Worker: ScanResult
      Worker-->>Browser: {progress, totalHashes}
    end
    alt solution found
      Worker-->>Browser: {ok: true, result}
      Browser->>Browser: grace timeout → display nonce/hash
    else exhausted
      Worker-->>Browser: {done}
      Browser->>Browser: "Nonce space exhausted"
    end
  end
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.38% 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
Title check ✅ Passed The PR title clearly summarizes the main change: introducing a Zensical-based documentation site with WASM demos and GitHub Pages workflow, which aligns with the extensive changes across documentation, samples, and CI/CD files.
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 The PR description comprehensively explains the motivation for infrastructure changes, technical implementations, testing approach, and includes supporting documentation.

✏️ 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 15, 2026

Copy link
Copy Markdown

Warning

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

Potential conflicts

@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: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

80-92: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

default is being described as a feature toggle when it is really baseline capability.

The docs should describe no_std + alloc as the always-available baseline and avoid implying that Cargo's default feature enables it.

  • README.md#L80-L92: reword the table row to describe the baseline rather than a feature flag.
  • docs/zen/index.md#L82-L92: make the same wording change in the docs site page.
🤖 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 `@README.md` around lines 80 - 92, The table describing features incorrectly
frames `no_std + alloc` as a Cargo feature flag called `default` when it is
actually the always-available baseline capability. In README.md (lines 80-92)
and docs/zen/index.md (lines 82-92), reword the `default` table row to clearly
describe `no_std + alloc` as the baseline that is always available, rather than
implying it is enabled by Cargo's default feature. Ensure the updated wording
makes it clear this is not a feature toggle but rather the foundation that all
other features build upon.
🤖 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/pages.yml:
- Around line 32-34: The "Install wasm-pack" step uses curl to execute a remote
shell script (curl | sh), which presents a supply-chain security risk without
cryptographic verification. Replace the run command to use cargo install
wasm-pack with an explicit version pinned and the --locked flag to compile from
source or use verified crates.io distribution, eliminating the shell script
injection risk and ensuring reproducible builds.
- Around line 21-24: Replace all mutable GitHub Actions version references with
immutable full commit SHAs to eliminate supply-chain vulnerabilities. Locate
each actions/ reference that uses `@v`* or `@master` tags (such as actions/checkout,
and any other third-party actions), and pin each to its corresponding full
commit SHA instead. Additionally, add persist-credentials: false to the checkout
action step since this workflow does not perform any git push operations or
require credential persistence.

In `@contrib/lint/lint_codeql.py`:
- Around line 55-57: The path keys emitted for source files must match what the
QL consumer expects in the sourceLineContent join predicates. The file key
emission (around lines 69-74) was changed to repo-root-relative format with the
pkgs/ prefix, but the corresponding path capture pattern in
contrib/codeql/lib/policy.qll still expects paths without this prefix, breaking
the sourceLineContent join. Align the path format consistently by either
removing the pkgs/ prefix from the emitted file keys in the generator (lines
69-74, 196-201) or updating the path capture pattern in policy.qll to match the
new format with the pkgs/ prefix included.

In `@contrib/samples/parser/parser.rs`:
- Around line 66-69: Add a `# Errors` documentation section to both parser
functions that return Result types. The first function with rustdoc starting
around line 66 needs documentation explaining what errors can be returned, and
the second function around lines 90-92 has the same requirement. Each `# Errors`
section should describe the failure conditions that cause the Result to return
an error variant, following the rustdoc coding guidelines for Result-returning
functions.

In `@contrib/samples/parser/style.css`:
- Around line 3-4: The font-family-name-quotes stylelint rule is being violated
due to inconsistent quoting of font family names. In
contrib/samples/parser/style.css at lines 3-4 (anchor location) and lines 32-33
(sibling location), remove the quotes around 'SFMono-Regular' to make it
consistent with the stylelint configuration and ensure the font family names
follow the proper quoting convention for the configured rule.

In `@contrib/samples/solver/index.js`:
- Around line 157-166: The current isU32 and isI32 functions use parseInt which
accepts partial input with trailing garbage (e.g., parseInt("123abc", 10)
returns 123), allowing malformed values to pass validation. Replace the
parseInt-based validation with a stricter approach that validates the entire
input string matches the numeric format exactly, rejecting any trailing
non-numeric characters. This same issue appears in the functions at lines
234-240 and must also be fixed there to ensure consistent validation across all
numeric type-checking functions.

In `@contrib/samples/solver/style.css`:
- Around line 51-52: In the font-family property declaration, remove the single
quotes around the font name SFMono-Regular (changing 'SFMono-Regular' to
SFMono-Regular) to comply with the stylelint font-family-name-quotes rule, while
keeping the quotes around other font names like 'SF Mono' and 'Liberation Mono'
as they are multi-word names that require quoting.

In `@contrib/samples/solver/worker.js`:
- Around line 13-18: The `await ready` statement in the worker onmessage handler
is executing before the try block, which means WASM initialization failures
won't be caught and the main thread will hang without an error. Move the `await
ready` statement inside the try block (right after the opening brace of try) so
that any WASM initialization failures are properly caught by the catch block and
appropriate error handling can occur.

In `@contrib/zen/__init__.py`:
- Around line 82-86: The blank line handling in the body_line loop (lines 82–86)
breaks admonition block formatting by not maintaining indentation. When
body_line is falsy (line 85), the code appends an empty string "", but it should
append four spaces "    " instead to keep blank lines indented at the same level
as non-empty body lines. This prevents MkDocs admonition blocks from terminating
prematurely when encountering paragraph separators.

In `@docs/README.md`:
- Around line 16-18: The extras notation in the three dependency bullets for
Zensical, PyMarkdown, and rjsmin uses an incorrect format of `[.dev]` which is
inconsistent with the install command reference at line 14. Change the notation
from `[.dev]` to `[dev]` in all three bullet points to match the correct extras
syntax and maintain consistency throughout the documentation.

In `@pkgs/primitives/src/prelude.rs`:
- Around line 15-21: The round function shim defined in the cfg_if block in
prelude.rs (lines 15-21) is only used in serialize.rs which is gated by the
serde feature, but the shim itself is defined unconditionally whenever std is
available, causing dead-code warnings in builds without serde. Wrap the entire
cfg_if block that contains the round function definition with an additional
#[cfg(feature = "serde")] attribute so the shim is only compiled when the serde
feature is actually enabled, matching the feature gate of its only caller in
serialize.rs.

---

Outside diff comments:
In `@README.md`:
- Around line 80-92: The table describing features incorrectly frames `no_std +
alloc` as a Cargo feature flag called `default` when it is actually the
always-available baseline capability. In README.md (lines 80-92) and
docs/zen/index.md (lines 82-92), reword the `default` table row to clearly
describe `no_std + alloc` as the baseline that is always available, rather than
implying it is enabled by Cargo's default feature. Ensure the updated wording
makes it clear this is not a feature toggle but rather the foundation that all
other features build upon.
🪄 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: 185583a3-0d70-40b8-8dd6-5fce2f99f612

📥 Commits

Reviewing files that changed from the base of the PR and between 4a1b68e and 1997dd3.

⛔ Files ignored due to path filters (3)
  • Cargo.lock is excluded by !**/*.lock
  • contrib/samples/Cargo.lock is excluded by !**/*.lock
  • docs/zen/logo.svg is excluded by !**/*.svg
📒 Files selected for processing (46)
  • .github/workflows/build_msrv.yml
  • .github/workflows/build_nightly.yml
  • .github/workflows/build_stable.yml
  • .github/workflows/pages.yml
  • .gitignore
  • CLAUDE.md
  • README.md
  • contrib/__init__.py
  • contrib/build_docs.py
  • contrib/codeql/codeql-config.yml
  • contrib/codeql/import.ql
  • contrib/codeql/lib/policy.qll
  • contrib/common.py
  • contrib/js/eslint.config.mjs
  • contrib/lint/common.py
  • contrib/lint/common.py
  • contrib/lint/lint_codeql.py
  • contrib/lint/lint_javascript.py
  • contrib/lint/lint_markdown.py
  • contrib/lint/lint_rust.py
  • contrib/lint/lint_semgrep.py
  • contrib/lint_all.py
  • contrib/samples/Cargo.toml
  • contrib/samples/common.css
  • contrib/samples/parser/Cargo.toml
  • contrib/samples/parser/index.js
  • contrib/samples/parser/parser.rs
  • contrib/samples/parser/style.css
  • contrib/samples/solver/Cargo.toml
  • contrib/samples/solver/index.js
  • contrib/samples/solver/solver.rs
  • contrib/samples/solver/style.css
  • contrib/samples/solver/worker.js
  • contrib/zen/__init__.py
  • docs/README.md
  • docs/guide_rust.md
  • docs/zen/index.md
  • docs/zen/samples/index.md
  • docs/zen/samples/parser/index.md
  • docs/zen/samples/solver/index.md
  • docs/zen/style.css
  • pkgs/primitives/Cargo.toml
  • pkgs/primitives/src/prelude.rs
  • pkgs/primitives/src/serialize.rs
  • pyproject.toml
  • zensical.toml

Comment on lines +21 to +24
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 1

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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "pages.yml" -path "*/.github/workflows/*" | head -5

Repository: dashpay/base-sdk

Length of output: 90


🏁 Script executed:

cat -n ./.github/workflows/pages.yml

Repository: dashpay/base-sdk

Length of output: 2265


🌐 Web query:

GitHub Actions security best practices pin commit SHA persist-credentials

💡 Result:

Securing GitHub Actions workflows involves two critical practices: pinning actions to commit SHAs to ensure immutability [1][2] and explicitly managing credential persistence to prevent unauthorized access [3][4]. Pinning Actions to Commit SHAs Pinning an action to a full-length commit SHA is the only way to ensure the action is an immutable release [1]. Unlike tags or branches, which are mutable and can be updated or redirected by a malicious actor to compromise your workflow [2][5], a commit SHA is immutable once a commit exists [2]. - Implementation: Reference the full-length SHA in your workflow file. It is recommended to include the version tag as a comment for readability [6][5]. - uses: actions/checkout@3df4ab1 # v4.0.0 - Governance: GitHub supports organization-level policies that enforce SHA pinning for all actions [7][2]. If enabled, any workflow using a tag or branch will fail [2][6]. - Automation: Use tools like Dependabot or Renovate (specifically the helpers:pinGitHubActionDigests preset) to automate updates to your pinned SHAs, ensuring you benefit from security patches without sacrificing immutability [2][6]. Managing Credential Persistence The actions/checkout action defaults to persist-credentials: true, which stores the GITHUB_TOKEN (or other credentials) in the runner's local Git configuration [8][3]. This exposes the token to every subsequent step in the job, increasing the risk of credential leakage if a malicious action or script is executed [3][4][9]. - Implementation: Explicitly set persist-credentials: false in your checkout steps unless your workflow specifically requires pushing commits back to the repository [3][4]. - uses: actions/checkout@v4 with: persist-credentials: false - Security Rationale: Setting this to false prevents the token from being persisted in the Git configuration file, thereby limiting the risk of it being accessed by third-party actions, logged, or accidentally included in build artifacts [3][10]. If your workflow must push changes, use a scoped GITHUB_TOKEN with the minimum required permissions [3][11]. Additional Best Practices - Principle of Least Privilege: Always set the default permissions for the GITHUB_TOKEN to read-only at the workflow or job level and grant specific write access only when necessary [12][11]. - Automated Auditing: Use tools like Zizmor or similar linters to audit your workflows for missing SHA pins and unsafe credential configurations [6][3][10].

Citations:


Pin third-party GitHub Actions to immutable commit SHAs and disable credential persistence.

Lines 22, 27, 36, 44, 56, and 76 use mutable version tags (@v*/@master), which creates supply-chain vulnerabilities. Pin each action to its full commit SHA instead. Additionally, add persist-credentials: false to the checkout step (lines 21-24) since this workflow performs no git push or authentication operations.

Suggested hardening diff
      - name: Checkout
        uses: actions/checkout@v6
+        uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
         with:
           fetch-depth: 1
+          persist-credentials: false

      - name: Install Rust toolchain
-        uses: dtolnay/rust-toolchain@master
+        uses: dtolnay/rust-toolchain@<pinned-commit-sha>

      - name: Set up Python
-        uses: actions/setup-python@v6
+        uses: actions/setup-python@<pinned-commit-sha>

      - name: Manage cargo registry
-        uses: actions/cache@v5
+        uses: actions/cache@<pinned-commit-sha>

      - name: Upload Pages artifact
-        uses: actions/upload-pages-artifact@v5
+        uses: actions/upload-pages-artifact@<pinned-commit-sha>

      - name: Deploy to GitHub Pages
-        uses: actions/deploy-pages@v5
+        uses: actions/deploy-pages@<pinned-commit-sha>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Checkout
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
with:
fetch-depth: 1
persist-credentials: false
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 21-24: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 22-22: 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/pages.yml around lines 21 - 24, Replace all mutable GitHub
Actions version references with immutable full commit SHAs to eliminate
supply-chain vulnerabilities. Locate each actions/ reference that uses `@v`* or
`@master` tags (such as actions/checkout, and any other third-party actions), and
pin each to its corresponding full commit SHA instead. Additionally, add
persist-credentials: false to the checkout action step since this workflow does
not perform any git push operations or require credential persistence.

Source: Linters/SAST tools

Comment thread .github/workflows/pages.yml
Comment thread contrib/lint/lint_codeql.py
Comment on lines +66 to +69
/// Parses a hex-encoded raw block or block header and returns a JSON string.
/// Inputs of exactly 80 bytes are decoded as a block header; longer inputs are
/// decoded as a full block.
#[wasm_bindgen]

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

Add # Errors sections to the exported Result APIs.

Both public parser functions return Result<_, _> but their rustdoc currently omits the required # Errors section.

Proposed fix
 /// Parses a hex-encoded raw block or block header and returns a JSON string.
 /// Inputs of exactly 80 bytes are decoded as a block header; longer inputs are
 /// decoded as a full block.
+///
+/// # Errors
+/// Returns an error if the input is empty, not valid hex, decoding fails,
+/// or JSON serialization fails.
 #[wasm_bindgen]
 pub fn parse_block_hex(hex_str: &str) -> Result<String, String> {
@@
 /// Parses a hex-encoded raw transaction and returns a JSON string.
+///
+/// # Errors
+/// Returns an error if the input is empty, not valid hex, transaction decoding
+/// fails, or JSON serialization fails.
 #[wasm_bindgen]
 pub fn parse_tx_hex(hex_str: &str) -> Result<String, String> {

As per coding guidelines, "Document # Errors for Result-returning functions."

Also applies to: 90-92

🤖 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/samples/parser/parser.rs` around lines 66 - 69, Add a `# Errors`
documentation section to both parser functions that return Result types. The
first function with rustdoc starting around line 66 needs documentation
explaining what errors can be returned, and the second function around lines
90-92 has the same requirement. Each `# Errors` section should describe the
failure conditions that cause the Result to return an error variant, following
the rustdoc coding guidelines for Result-returning functions.

Source: Coding guidelines

Comment thread contrib/samples/parser/style.css Outdated
Comment thread contrib/samples/solver/style.css Outdated
Comment thread contrib/samples/solver/worker.js
Comment thread contrib/zen/__init__.py Outdated
Comment thread docs/README.md Outdated
Comment thread pkgs/primitives/src/prelude.rs

@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: 1

♻️ Duplicate comments (1)
.github/workflows/pages.yml (1)

22-22: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin workflow actions to immutable commit SHAs.

These uses: references are still tag/branch-based, so execution can drift without a PR diff. Pin each action to a full 40-char SHA (optionally keep the version tag as an inline comment).

#!/bin/bash
# Verify any non-SHA-pinned actions in this workflow.
rg -nP '^\s*uses:\s*[^@]+@(?![0-9a-f]{40}\b).+' .github/workflows/pages.yml

Also applies to: 28-28, 37-37, 45-45, 57-57, 77-77

🤖 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/pages.yml at line 22, Replace all tag and branch-based
action references in the workflow file with their immutable full 40-character
commit SHAs. For the actions/checkout action at line 22 and all other uses
statements at lines 28, 37, 45, 57, and 77, change each reference from formats
like `@v6`, `@main`, or other tag/branch formats to the corresponding full commit
SHA (you can optionally retain the version tag as an inline comment for
documentation). Verify the changes by running the provided regex command to
ensure no non-SHA-pinned actions remain in the workflow.

Source: Linters/SAST tools

🤖 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 `@contrib/samples/common.css`:
- Line 1: The `@import` statement in common.css is using the url() function
notation, which violates the configured stylelint import-notation rule. Remove
the url() function wrapper and instead use direct string notation for the import
statement, placing the URL directly as a string argument to `@import`.

---

Duplicate comments:
In @.github/workflows/pages.yml:
- Line 22: Replace all tag and branch-based action references in the workflow
file with their immutable full 40-character commit SHAs. For the
actions/checkout action at line 22 and all other uses statements at lines 28,
37, 45, 57, and 77, change each reference from formats like `@v6`, `@main`, or other
tag/branch formats to the corresponding full commit SHA (you can optionally
retain the version tag as an inline comment for documentation). Verify the
changes by running the provided regex command to ensure no non-SHA-pinned
actions remain in the workflow.
🪄 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: b0146ef6-3aa8-482f-8e1a-12cb85f7ad15

📥 Commits

Reviewing files that changed from the base of the PR and between 1997dd3 and c78bb1c.

⛔ Files ignored due to path filters (3)
  • Cargo.lock is excluded by !**/*.lock
  • contrib/samples/Cargo.lock is excluded by !**/*.lock
  • docs/zen/logo.svg is excluded by !**/*.svg
📒 Files selected for processing (44)
  • .github/workflows/build_msrv.yml
  • .github/workflows/build_nightly.yml
  • .github/workflows/build_stable.yml
  • .github/workflows/pages.yml
  • .gitignore
  • README.md
  • contrib/__init__.py
  • contrib/build_docs.py
  • contrib/codeql/codeql-config.yml
  • contrib/codeql/import.ql
  • contrib/codeql/lib/files.qll
  • contrib/codeql/lib/policy.qll
  • contrib/common.py
  • contrib/js/eslint.config.mjs
  • contrib/lint/common.py
  • contrib/lint/common.py
  • contrib/lint/lint_codeql.py
  • contrib/lint/lint_javascript.py
  • contrib/lint/lint_rust.py
  • contrib/lint/lint_semgrep.py
  • contrib/lint_all.py
  • contrib/samples/Cargo.toml
  • contrib/samples/common.css
  • contrib/samples/parser/Cargo.toml
  • contrib/samples/parser/index.js
  • contrib/samples/parser/parser.rs
  • contrib/samples/parser/style.css
  • contrib/samples/solver/Cargo.toml
  • contrib/samples/solver/index.js
  • contrib/samples/solver/solver.rs
  • contrib/samples/solver/style.css
  • contrib/samples/solver/worker.js
  • contrib/zen/__init__.py
  • docs/README.md
  • docs/zen/index.md
  • docs/zen/samples/index.md
  • docs/zen/samples/parser/index.md
  • docs/zen/samples/solver/index.md
  • docs/zen/style.css
  • pkgs/primitives/Cargo.toml
  • pkgs/primitives/src/prelude.rs
  • pkgs/primitives/src/serialize.rs
  • pyproject.toml
  • zensical.toml
✅ Files skipped from review due to trivial changes (7)
  • contrib/codeql/lib/files.qll
  • .github/workflows/build_stable.yml
  • docs/zen/samples/index.md
  • docs/zen/samples/parser/index.md
  • contrib/samples/parser/style.css
  • contrib/codeql/codeql-config.yml
  • README.md
🚧 Files skipped from review as they are similar to previous changes (27)
  • contrib/init.py
  • docs/README.md
  • .github/workflows/build_nightly.yml
  • pkgs/primitives/src/serialize.rs
  • contrib/samples/Cargo.toml
  • .github/workflows/build_msrv.yml
  • docs/zen/samples/solver/index.md
  • docs/zen/style.css
  • pkgs/primitives/Cargo.toml
  • contrib/samples/solver/Cargo.toml
  • contrib/lint/lint_javascript.py
  • pkgs/primitives/src/prelude.rs
  • contrib/lint/lint_semgrep.py
  • contrib/js/eslint.config.mjs
  • zensical.toml
  • contrib/lint/common.py
  • contrib/samples/solver/style.css
  • contrib/lint_all.py
  • contrib/samples/parser/index.js
  • pyproject.toml
  • contrib/samples/solver/worker.js
  • contrib/samples/parser/Cargo.toml
  • contrib/samples/parser/parser.rs
  • contrib/samples/solver/solver.rs
  • contrib/codeql/import.ql
  • contrib/samples/solver/index.js
  • contrib/zen/init.py

Comment thread contrib/samples/common.css Outdated

@thephez thephez 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.

A few minor things to look at

Comment thread docs/README.md
Comment thread docs/zen/index.md Outdated
Comment thread docs/zen/index.md
Comment thread docs/zen/samples/index.md Outdated
Comment thread docs/zen/samples/index.md Outdated
Comment thread README.md Outdated

@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: 4

♻️ Duplicate comments (2)
.github/workflows/pages.yml (1)

22-22: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin all GitHub Actions to immutable commit SHAs.

Mutable refs (@v*, @master) are still used, which leaves this workflow exposed to upstream ref retargeting. Please pin each uses: entry to a full 40-char SHA.

#!/bin/bash
# Verify all unpinned uses in this workflow
rg -nP '^\s*uses:\s*[^@]+@(?![0-9a-f]{40}\b).+$' .github/workflows/pages.yml

Also applies to: 28-28, 37-37, 45-45, 57-57, 77-77

🤖 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/pages.yml at line 22, All GitHub Actions uses entries in
the workflow file are using mutable version references like `@v6` instead of
immutable full 40-character commit SHAs. Replace each mutable uses entry
(including actions/checkout@v6 and others referenced at lines 28, 37, 45, 57,
and 77) with its corresponding action pinned to a complete 40-character commit
SHA to prevent upstream ref retargeting and ensure workflow security.

Source: Linters/SAST tools

contrib/samples/solver/index.js (1)

199-205: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Numeric validation is still bypassable via permissive parsing.

parseBits() and DASH amount conversion still use permissive parsing, so malformed values (e.g. trailing garbage) can be accepted and used in solve payload construction.

Suggested hardening
 function parseBits() {
   const v = bitsInput.value.trim();
   if (bitsMode === "hex") {
-    return parseInt(v, 16);
+    if (!/^(?:0x)?[0-9a-fA-F]{1,8}$/.test(v)) return NaN;
+    return Number.parseInt(v, 16);
   }
-  return parseInt(v, 10);
+  if (!/^(0|[1-9]\d*)$/.test(v)) return NaN;
+  return Number.parseInt(v, 10);
 }
@@
 function getAmountDuffs() {
   const v = amountInput.value.trim();
   if (amountMode === "duffs") {
-    return v;
+    return /^(0|[1-9]\d*)$/.test(v) ? v : "";
   }
-  return String(Math.round(parseFloat(v) * DUFFS_PER_DASH));
+  if (!/^(?:0|[1-9]\d*)(?:\.\d{1,8})?$/.test(v)) return "";
+  return String(Math.round(Number(v) * DUFFS_PER_DASH));
 }
Does JavaScript `parseInt("123abc", 10)` return `123` by ignoring trailing characters?

Also applies to: 234-239, 243-249

🤖 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/samples/solver/index.js` around lines 199 - 205, The numeric
validation for difficulty and amount values is still vulnerable to permissive
parsing that accepts trailing garbage characters. The amount validation
correctly uses a strict regex pattern /^\d+$/ to ensure the entire string
contains only digits, but the parseBits() function and DASH amount conversion
still use permissive parsing (e.g., JavaScript's parseInt which ignores trailing
characters). Apply the same strict validation pattern used for amount validation
to the difficulty and amount conversion functions, ensuring they reject any
input with trailing non-numeric characters. This fix should be applied
consistently across all locations where numeric values are parsed (the
isU32(String(parseBits())) block and the amount conversion sections mentioned at
lines 234-239 and 243-249).
🧹 Nitpick comments (2)
contrib/samples/solver/style.css (1)

110-144: 💤 Low value

Consider using CSS variables for admonition colors.

The admonition colors are hardcoded hex values. While this may be intentional to match GitHub alert styling, using CSS variables would improve maintainability and make theme customization easier.

♻️ Example refactor using CSS variables

Define variables in the root scope:

`#wasm-genesis` {
  --genesis-warn-bg: `#fef9e7`;
  --genesis-warn-fg: `#6e5b00`;
  --genesis-warn-border: `#d4a017`;
  /* ... similar for note and danger */
}

[data-md-color-scheme="slate"] `#wasm-genesis` {
  --genesis-warn-bg: `#3b3000`;
  --genesis-warn-fg: `#fcd34d`;
  --genesis-warn-border: `#ca8a04`;
  /* ... similar for note and danger */
}

Then use them:

`#wasm-genesis` .genesis-warn {
  border-left: 3px solid var(--genesis-warn-border);
  background: var(--genesis-warn-bg);
  color: var(--genesis-warn-fg);
}
🤖 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/samples/solver/style.css` around lines 110 - 144, The .genesis-warn,
.genesis-note, and .genesis-danger classes contain hardcoded hex color values
that should be replaced with CSS variables for improved maintainability and
theme customization. Define CSS custom properties (variables) at the
`#wasm-genesis` scope for each admonition type covering background, text color,
and border colors, then define corresponding variables again within the
[data-md-color-scheme="slate"] `#wasm-genesis` block for dark mode styling.
Finally, update each of the three admonition classes (.genesis-warn,
.genesis-note, .genesis-danger) to use var() references instead of hardcoded hex
values.
contrib/zen/__init__.py (1)

2-2: 💤 Low value

Consider removing or changing the encoding declaration.

The latin-1 encoding declaration is unusual for Python 3, which defaults to UTF-8. Since the file content appears to be pure ASCII, the encoding declaration is unnecessary and could cause issues if non-ASCII characters are added later.

♻️ Simplify by removing the encoding line
 #!/usr/bin/env python3
-# coding: latin-1
🤖 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/zen/__init__.py` at line 2, Remove the `# coding: latin-1` encoding
declaration from the beginning of the file in contrib/zen/__init__.py. Python 3
defaults to UTF-8 encoding, so this explicit declaration is unnecessary for
ASCII-only content and can cause issues if non-ASCII characters are introduced
later. Simply delete this line to align with Python 3 best practices.
🤖 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 `@contrib/build_docs.py`:
- Around line 85-89: The shutil.copy2 calls in the _copy_artifacts function
assume that the destination directory path already exists, but they do not
create these directories if they are missing, which will cause
FileNotFoundError. Before each shutil.copy2 call (including the one for
common.css and the additional ones mentioned at lines 104-108), add a line to
create the parent directories by calling mkdir with parents=True and
exist_ok=True on the destination path's parent directory to ensure all required
directories exist before attempting to copy files.

In `@contrib/lint/lint_markdown.py`:
- Around line 41-45: The prefix path construction using str(repo_root) + "/"
only handles forward slashes, which fails when the linter outputs backslash
paths on Windows or other platforms. Fix the prefix variable to use a
platform-agnostic path separator (use pathlib.Path or os.path.normpath to
normalize the repo_root path), and ensure that when replacing the prefix in both
the stdout and stderr lines within the respective for loops, the replacement
accounts for the normalized path separator used by the operating system. This
will make the path stripping consistent across different path separator
conventions.

In `@contrib/zen/__init__.py`:
- Line 53: The direct dictionary access to _ALERT_KIND using match.group(1) at
line 53 will raise a KeyError if the source Markdown contains an unknown alert
type (e.g., [!ERROR] or [!INFO]). Add validation to check if the alert type from
match.group(1) exists as a key in the _ALERT_KIND dictionary before accessing
it. Choose a defensive approach either to gracefully skip unknown alerts by
using a default value or .get() method, or fail fast by raising a clear error
message that describes which invalid alert type was encountered.

In `@docs/zen/index.md`:
- Around line 3-5: The documentation intro in the SDK overview section currently
uses "interact with the Dash blockchain" which misleadingly implies networking
and runtime chain interaction capabilities. Revise the opening description to
clarify that the Base SDK's scope is limited to encoding, decoding,
construction, and validation of blockchain data structures, removing any
language that suggests network or runtime interaction capabilities. Focus the
description on the data-level operations and the rust-bitcoin foundation it
builds upon rather than implying full blockchain interaction.

---

Duplicate comments:
In @.github/workflows/pages.yml:
- Line 22: All GitHub Actions uses entries in the workflow file are using
mutable version references like `@v6` instead of immutable full 40-character
commit SHAs. Replace each mutable uses entry (including actions/checkout@v6 and
others referenced at lines 28, 37, 45, 57, and 77) with its corresponding action
pinned to a complete 40-character commit SHA to prevent upstream ref retargeting
and ensure workflow security.

In `@contrib/samples/solver/index.js`:
- Around line 199-205: The numeric validation for difficulty and amount values
is still vulnerable to permissive parsing that accepts trailing garbage
characters. The amount validation correctly uses a strict regex pattern /^\d+$/
to ensure the entire string contains only digits, but the parseBits() function
and DASH amount conversion still use permissive parsing (e.g., JavaScript's
parseInt which ignores trailing characters). Apply the same strict validation
pattern used for amount validation to the difficulty and amount conversion
functions, ensuring they reject any input with trailing non-numeric characters.
This fix should be applied consistently across all locations where numeric
values are parsed (the isU32(String(parseBits())) block and the amount
conversion sections mentioned at lines 234-239 and 243-249).

---

Nitpick comments:
In `@contrib/samples/solver/style.css`:
- Around line 110-144: The .genesis-warn, .genesis-note, and .genesis-danger
classes contain hardcoded hex color values that should be replaced with CSS
variables for improved maintainability and theme customization. Define CSS
custom properties (variables) at the `#wasm-genesis` scope for each admonition
type covering background, text color, and border colors, then define
corresponding variables again within the [data-md-color-scheme="slate"]
`#wasm-genesis` block for dark mode styling. Finally, update each of the three
admonition classes (.genesis-warn, .genesis-note, .genesis-danger) to use var()
references instead of hardcoded hex values.

In `@contrib/zen/__init__.py`:
- Line 2: Remove the `# coding: latin-1` encoding declaration from the beginning
of the file in contrib/zen/__init__.py. Python 3 defaults to UTF-8 encoding, so
this explicit declaration is unnecessary for ASCII-only content and can cause
issues if non-ASCII characters are introduced later. Simply delete this line to
align with Python 3 best practices.
🪄 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: 242fdc01-610c-4230-8702-d39ed95edf31

📥 Commits

Reviewing files that changed from the base of the PR and between c78bb1c and 85e5244.

⛔ Files ignored due to path filters (3)
  • Cargo.lock is excluded by !**/*.lock
  • contrib/samples/Cargo.lock is excluded by !**/*.lock
  • docs/zen/logo.svg is excluded by !**/*.svg
📒 Files selected for processing (47)
  • .github/workflows/build_msrv.yml
  • .github/workflows/build_nightly.yml
  • .github/workflows/build_stable.yml
  • .github/workflows/pages.yml
  • .gitignore
  • CLAUDE.md
  • README.md
  • contrib/__init__.py
  • contrib/build_docs.py
  • contrib/codeql/codeql-config.yml
  • contrib/codeql/import.ql
  • contrib/codeql/lib/files.qll
  • contrib/codeql/lib/policy.qll
  • contrib/common.py
  • contrib/js/eslint.config.mjs
  • contrib/lint/common.py
  • contrib/lint/common.py
  • contrib/lint/lint_codeql.py
  • contrib/lint/lint_javascript.py
  • contrib/lint/lint_markdown.py
  • contrib/lint/lint_rust.py
  • contrib/lint/lint_semgrep.py
  • contrib/lint_all.py
  • contrib/samples/Cargo.toml
  • contrib/samples/common.css
  • contrib/samples/parser/Cargo.toml
  • contrib/samples/parser/index.js
  • contrib/samples/parser/parser.rs
  • contrib/samples/parser/style.css
  • contrib/samples/solver/Cargo.toml
  • contrib/samples/solver/index.js
  • contrib/samples/solver/solver.rs
  • contrib/samples/solver/style.css
  • contrib/samples/solver/worker.js
  • contrib/zen/__init__.py
  • docs/README.md
  • docs/guide_rust.md
  • docs/zen/index.md
  • docs/zen/samples/index.md
  • docs/zen/samples/parser/index.md
  • docs/zen/samples/solver/index.md
  • docs/zen/style.css
  • pkgs/primitives/Cargo.toml
  • pkgs/primitives/src/prelude.rs
  • pkgs/primitives/src/serialize.rs
  • pyproject.toml
  • zensical.toml
✅ Files skipped from review due to trivial changes (8)
  • contrib/lint/lint_semgrep.py
  • contrib/init.py
  • docs/zen/samples/index.md
  • contrib/samples/parser/style.css
  • README.md
  • CLAUDE.md
  • docs/guide_rust.md
  • docs/zen/style.css
🚧 Files skipped from review as they are similar to previous changes (27)
  • contrib/codeql/codeql-config.yml
  • docs/README.md
  • contrib/samples/Cargo.toml
  • contrib/codeql/lib/files.qll
  • docs/zen/samples/parser/index.md
  • pkgs/primitives/src/prelude.rs
  • .gitignore
  • contrib/lint_all.py
  • pkgs/primitives/Cargo.toml
  • contrib/samples/solver/worker.js
  • pyproject.toml
  • pkgs/primitives/src/serialize.rs
  • contrib/lint/lint_javascript.py
  • contrib/lint/common.py
  • contrib/samples/parser/Cargo.toml
  • .github/workflows/build_stable.yml
  • contrib/samples/parser/parser.rs
  • .github/workflows/build_msrv.yml
  • zensical.toml
  • contrib/samples/common.css
  • contrib/samples/solver/solver.rs
  • .github/workflows/build_nightly.yml
  • docs/zen/samples/solver/index.md
  • contrib/samples/solver/Cargo.toml
  • contrib/lint/common.py
  • contrib/js/eslint.config.mjs
  • contrib/samples/parser/index.js

Comment thread contrib/build_docs.py
Comment on lines +41 to +45
prefix = str(repo_root) + "/"
for line in result.stdout.splitlines():
print(line.replace(prefix, ""))
for line in result.stderr.splitlines():
print(line.replace(prefix, ""), file=sys.stderr)

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

Normalize repo-root path stripping across path separators.

This replacement only handles / paths. If the linter emits \ paths, repo-root trimming won’t apply and output becomes inconsistent.

Proposed fix
-  prefix = str(repo_root) + "/"
-  for line in result.stdout.splitlines():
-    print(line.replace(prefix, ""))
-  for line in result.stderr.splitlines():
-    print(line.replace(prefix, ""), file=sys.stderr)
+  prefixes = (f"{repo_root}/", f"{repo_root}\\")
+
+  def strip_repo_root(line: str) -> str:
+    for prefix in prefixes:
+      if line.startswith(prefix):
+        return line[len(prefix):]
+    return line
+
+  for line in result.stdout.splitlines():
+    print(strip_repo_root(line))
+  for line in result.stderr.splitlines():
+    print(strip_repo_root(line), file=sys.stderr)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
prefix = str(repo_root) + "/"
for line in result.stdout.splitlines():
print(line.replace(prefix, ""))
for line in result.stderr.splitlines():
print(line.replace(prefix, ""), file=sys.stderr)
prefixes = (f"{repo_root}/", f"{repo_root}\\")
def strip_repo_root(line: str) -> str:
for prefix in prefixes:
if line.startswith(prefix):
return line[len(prefix):]
return line
for line in result.stdout.splitlines():
print(strip_repo_root(line))
for line in result.stderr.splitlines():
print(strip_repo_root(line), file=sys.stderr)
🤖 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_markdown.py` around lines 41 - 45, The prefix path
construction using str(repo_root) + "/" only handles forward slashes, which
fails when the linter outputs backslash paths on Windows or other platforms. Fix
the prefix variable to use a platform-agnostic path separator (use pathlib.Path
or os.path.normpath to normalize the repo_root path), and ensure that when
replacing the prefix in both the stdout and stderr lines within the respective
for loops, the replacement accounts for the normalized path separator used by
the operating system. This will make the path stripping consistent across
different path separator conventions.

Comment thread contrib/zen/__init__.py
index += 1
continue

level = _ALERT_KIND[match.group(1)]

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 | 🟠 Major | ⚡ Quick win

Add validation to prevent KeyError on unknown alert types.

If the source Markdown contains an alert type not defined in _ALERT_KIND (e.g., [!ERROR] or [!INFO]), line 53 will raise a KeyError and crash the documentation build. This creates a fragile preprocessing step.

🛡️ Defensive handling options

Option 1: Skip unknown alerts (graceful degradation)

-      level = _ALERT_KIND[match.group(1)]
+      alert_type = match.group(1)
+      if alert_type not in _ALERT_KIND:
+        output.append(line)
+        index += 1
+        continue
+      level = _ALERT_KIND[alert_type]
       output.append(f"!!! {level}")

Option 2: Fail fast with clear error message

-      level = _ALERT_KIND[match.group(1)]
+      alert_type = match.group(1)
+      if alert_type not in _ALERT_KIND:
+        msg = f"Unsupported GFM alert type: {alert_type}"
+        raise ValueError(msg)
+      level = _ALERT_KIND[alert_type]
       output.append(f"!!! {level}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
level = _ALERT_KIND[match.group(1)]
alert_type = match.group(1)
if alert_type not in _ALERT_KIND:
msg = f"Unsupported GFM alert type: {alert_type}"
raise ValueError(msg)
level = _ALERT_KIND[alert_type]
🤖 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/zen/__init__.py` at line 53, The direct dictionary access to
_ALERT_KIND using match.group(1) at line 53 will raise a KeyError if the source
Markdown contains an unknown alert type (e.g., [!ERROR] or [!INFO]). Add
validation to check if the alert type from match.group(1) exists as a key in the
_ALERT_KIND dictionary before accessing it. Choose a defensive approach either
to gracefully skip unknown alerts by using a default value or .get() method, or
fail fast by raising a clear error message that describes which invalid alert
type was encountered.

Comment thread docs/zen/index.md
Comment on lines +3 to +5
The Base SDK for Dash is a collection of packages that enable applications to parse, construct and interact with the
Dash blockchain. This is achieved by leveraging the [`rust-bitcoin`](https://github.com/rust-bitcoin/rust-bitcoin)
ecosystem to provide a framework that builds upon existing, familiar APIs and contract expectations.

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

Clarify SDK scope to avoid implying built-in networking.

The current intro wording can read as runtime chain/network interaction. Consider tightening this to encoding/decoding, construction, and validation of blockchain data structures.

Based on learnings, no crate currently implements networking and the SDK scope is encoding/decoding plus data types.

🤖 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 `@docs/zen/index.md` around lines 3 - 5, The documentation intro in the SDK
overview section currently uses "interact with the Dash blockchain" which
misleadingly implies networking and runtime chain interaction capabilities.
Revise the opening description to clarify that the Base SDK's scope is limited
to encoding, decoding, construction, and validation of blockchain data
structures, removing any language that suggests network or runtime interaction
capabilities. Focus the description on the data-level operations and the
rust-bitcoin foundation it builds upon rather than implying full blockchain
interaction.

Source: Learnings

@thephez thephez 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.

Docs look okay to me

@kwvg kwvg merged commit 3d52e4a into dashpay:develop Jun 18, 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.

2 participants