Skip to content

Add Rust dependency audit to Makefile#354

Merged
leynos merged 30 commits into
mainfrom
feat/cargo-audit-to-makefile
May 26, 2026
Merged

Add Rust dependency audit to Makefile#354
leynos merged 30 commits into
mainfrom
feat/cargo-audit-to-makefile

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented May 19, 2026

Summary

This branch extends the repository audit gate so Rust dependencies are checked alongside the existing frontend audit workflow. It splits the Makefile target into frontend and Rust phases, installs cargo-audit in CI before the audit gate, updates vulnerable dependency versions found while exercising the expanded target, updates the CI Rust setup action to the current leynos/shared-actions default-branch commit, and raises the ws override to 8.20.1 so GHSA-58qx-3vcg-4xpx no longer fails the frontend audit.

No roadmap task, issue, or execplan was identified for this branch.

Review walkthrough

  • Start with Makefile to see how make audit now delegates to audit-node and rust-audit, including the scoped RUSTSEC-2023-0071 ignore for SQLx's optional MySQL dependency path.
  • Then review .github/workflows/ci.yml for the CI installation of cargo-audit and the updated leynos/shared-actions setup-rust pin at e4c6b0e200a057edf927c45c298e7ddf229b3934.
  • Check backend/Cargo.toml, Cargo.lock, package.json, and pnpm-lock.yaml for the dependency updates that clear actionable audit violations, including the ws 8.20.1 override used by Puppeteer's puppeteer-core dependency.
  • Finish with docs/repository-structure.md for the updated operator-facing description of the audit target.

Validation

  • make audit: passed; cargo audit reports no unignored vulnerabilities, the frontend audit no longer reports GHSA-58qx-3vcg-4xpx, and the SQLx optional MySQL RSA advisory remains ignored with a documented rationale.
  • make check-fmt: passed after the ws override update.
  • make lint: passed after the ws override update.
  • make test: passed after the ws override update; Rust nextest reported 1195 passed and 4 skipped, followed by passing frontend and workspace tests.
  • pnpm run test: passed as a focused audit-tooling regression check.
  • Earlier branch validation also included make fmt: passed.

Notes

cargo audit still reports allowed warnings for unmaintained, unsound, or yanked crates in the dependency graph. This branch addresses the audit violations that cause the target to fail and records the remaining RSA advisory as a scoped ignore because the workspace only enables PostgreSQL support for SQLx.

Summary by Sourcery

Add Rust dependency auditing to the repository-wide audit gate and refresh dependencies to satisfy the expanded checks.

New Features:

  • Introduce a Rust dependency audit step that runs cargo audit via the consolidated make audit target.

Enhancements:

  • Split the audit Makefile target into separate frontend and Rust phases with a scoped ignore for a known SQLx MySQL advisory.
  • Update backend Diesel-related Rust dependencies to newer compatible versions.
  • Refresh frontend devDependencies and overrides to resolve security advisories reported by the expanded audit.
  • Clarify repository documentation to describe the combined frontend and Rust audit behaviour.

CI:

  • Install cargo-audit in the CI workflow and bump the shared Rust setup action to the latest pinned commit.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Sorry @leynos, you have reached your weekly rate limit of 2500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 21ff04d8-2225-4dee-94fe-33f0bb6aee26

📥 Commits

Reviewing files that changed from the base of the PR and between 352b4a1 and 3052769.

📒 Files selected for processing (1)
  • docs/developers-guide.md

Summary

This PR extends the repository's audit gate to include Rust dependency checks via cargo-audit alongside the existing frontend Node.js audit. It pins pg-embed-setup-unpriv to 0.5.1 to resolve CI test timeouts caused by authentication failures in PostgreSQL embedded binary downloads, and bumps related Diesel dependencies. The Makefile is refactored to split make audit into audit-node and rust-audit targets, with a scoped ignore for RUSTSEC-2023-0071 (SQLx optional MySQL path). CI is updated to install cargo-audit@0.22.1 and pin POSTGRESQL_VERSION=16.10.0 to avoid rate-limiting issues.

Changes

Audit infrastructure and dependency checks

  • Makefile: Introduces audit-node and rust-audit targets; audit now depends on both. Adds CARGO_AUDIT_IGNORES := --ignore RUSTSEC-2023-0071 for SQLx's optional MySQL advisory.
  • CI workflow (.github/workflows/ci.yml): Installs cargo-audit via cargo binstall, pins shared Rust action to e4c6b0e200a0, and sets POSTGRESQL_VERSION=16.10.0 in test environment.
  • Backend dependencies (backend/Cargo.toml, Cargo.lock): Bumps pg_embedded_setup_unpriv from 0.5.0 to 0.5.1 (fixes CI test hangs from unauthenticated GitHub API rate limits), and upgrades Diesel (2.2→2.3), diesel-async (0.5→0.8), and diesel_migrations (2.2→2.3).
  • Frontend dependencies (package.json, pnpm-lock.yaml): Updates ajv, @mermaid-js/mermaid-cli, markdownlint-cli; raises ws override to 8.20.1 to address GHSA-58qx-3vcg-4xpx.

Security audit module refactoring

  • New modules:

    • security/audit-reporting.js: Exports partitionAdvisoriesById and reportUnexpectedAdvisories with injectable reportingIo adapter for testing.
    • security/audit-package-data.js: Centralises parsing, version-map building, and bulk-advisory normalisation logic; supports dependency-tree traversal and GHSA deduplication.
    • security/audit-exception-policy.js: Introduces assertNoExpired helper to validate exception expiry and date ordering with injectable policyIo adapter.
  • Refactored modules:

    • security/audit-utils.js: Shifted to dependency-injection pattern with auditIo and assertCompletedProcess adapters; delegates parsing and reporting to new modules; runAuditJson now accepts optional auditIo parameter.
    • security/validate-audit.js: Imports assertNoExpired from audit-exception-policy.js, removing local expiry logic.

Tests and documentation

  • New test suites: scripts/makefile-audit.test.mjs, scripts/security-audit-helpers.test.mjs, scripts/security-audit-reporting.test.mjs.
  • Updated tests: frontend-pwa/scripts/audit-utils.test.mjs extended with signal handling and bulk-advisory normalisation coverage.
  • Documentation updates:
    • docs/repository-structure.md: Describes combined frontend and Rust audit behaviour, security module layout.
    • docs/developers-guide.md: Documents dependency-audit quality gate, local setup with Corepack requirement, and audit-helper module patterns.

Rust roadmap tracking

  • Updated dead-code expectations in backend/src/inbound/http/schemas.rs, backend/src/outbound/persistence/models.rs, and backend/tests/example_data_runs_bdd.rs to reference docs/backend-roadmap.md 3.5.1 (issue #360) for future removal.

Validation

  • make audit passes: no unignored cargo audit vulnerabilities; frontend audit no longer reports GHSA-58qx-3vcg-4xpx after ws bump.
  • Rust tests: 1195 passed, 4 skipped.
  • Linting, formatting, and frontend tests all pass.

Notes

No new execplan document was identified for this branch. Issue #360 tracks removal of suppressed dead-code warnings once corresponding roadmap items are implemented.

Walkthrough

Split repository audits into audit-node and rust-audit, install cargo-audit in CI, add an architecture lint step, parameterise audit I/O and reporting helpers, add Makefile/audit tests, bump select dependencies, and standardise backend expect annotations.

Changes

Unified Audit and Dependency Maintenance

Layer / File(s) Summary
Audit infrastructure in Makefile
Makefile
CARGO and CARGO_AUDIT_IGNORES added; extend .PHONY; split audit into audit-node (workspace pnpm audits + pnpm run audit:validate) and rust-audit (check cargo-audit, run cargo audit --file Cargo.lock with ignore).
CI cargo-audit setup & lint step
.github/workflows/ci.yml
Update pinned setup-rust action commit; add Install cargo-audit step via cargo binstall --no-confirm for cargo-audit@0.22.1; add make lint-architecture step; pin POSTGRESQL_VERSION to =16.10.0.
Docs: repository & developer guides
docs/repository-structure.md, docs/developers-guide.md
Document make audit flow and security/ helpers, require Corepack for pnpm@10.15.1, describe pnpm→npm fallback, and add make audit to quality gates and local setup instructions.
Dependency version updates
backend/Cargo.toml, package.json
Bump pg_embedded_setup_unpriv, diesel/diesel-async/diesel_migrations, and frontend devDependencies/pnpm.overrides (@mermaid-js/mermaid-cli, ajv, markdownlint-cli, qs).
Makefile audit contract tests
scripts/makefile-audit.test.mjs
Add Vitest dry-run tests asserting make audit includes both Node and Rust audit steps, checks rust-audit cargo-audit availability/pinned version, and verifies cargo audit invocation with configured ignore; add execution test using temporary shims.
Frontend audit tests adjustments
frontend-pwa/scripts/audit-utils.test.mjs
Model pnpm process termination via nullable signal and status; add tests asserting runAuditJson() rejects on signalled pnpm commands and that bulk advisory normalisation omits github_advisory_id when absent.
Audit package-data helpers
security/audit-package-data.js
Add parseJsonOutput, buildVersionMap, loadPackageTrees, collectInstalledPackageVersions, and normalizeBulkAdvisories for pnpm tree parsing, version collection, GHSA extraction, deduplication and validation.
Audit IO abstraction & utils
security/audit-utils.js
Introduce defaultAuditIo, add assertCompletedProcess, thread auditIo through readRegistryUrl, fetchBulkAdvisories, runBulkAdvisoryAudit, and change exported runAuditJson(auditIo = defaultAuditIo) to use injected IO and preserve fallback behaviour; re-export package-data helpers.
Audit reporting helpers
security/audit-reporting.js
Add partitionAdvisoriesById(advisories, allowedIds) and reportUnexpectedAdvisories(unexpected, heading, reportingIo = defaultReportingIo) to partition advisories and report unexpected ones to stderr.
Audit exception policy & validate import
security/audit-exception-policy.js, security/validate-audit.js
Add assertNoExpired(entries, currentDate = new Date(), policyIo) and import it into validate-audit to centralise expiry and invalid-range checks.
Backend expect attributes and test struct
backend/src/..., backend/tests/...
Standardise #[expect(dead_code, reason = ...)] messages to reference docs/backend-roadmap.md 3.5.1; reformat DatabaseHandle tuple struct to attach the expect attribute explicitly; no API or schema changes.

Sequence Diagram(s)

sequenceDiagram
  participant Makefile
  participant PNPM as pnpm
  participant CI as CI
  participant CargoBinstall as cargo-binstall
  participant CargoAudit as cargo-audit
  participant AuditUtils as security/audit-utils.js
  participant PackageData as security/audit-package-data.js
  participant Registry as npm-registry

  Makefile->>PNPM: run workspace audits (pnpm -r --if-present run audit)
  Makefile->>PNPM: run pnpm run audit:validate
  CI->>CargoBinstall: run cargo binstall --no-confirm cargo-audit@0.22.1
  CargoBinstall->>CargoAudit: provide cargo-audit binary
  Makefile->>CargoAudit: invoke cargo audit --file Cargo.lock --ignore RUSTSEC-2023-0071
  PNPM-->>AuditUtils: stdout/json or retirement error
  AuditUtils->>PackageData: collectInstalledPackageVersions(auditIo)
  AuditUtils->>Registry: POST bulk advisory query with Abort (fallback)
  Registry-->>AuditUtils: bulk advisory payload
  AuditUtils->>PackageData: normalizeBulkAdvisories(payload)
Loading

Possibly related issues

Possibly related PRs

  • leynos/wildside#350 — Modifies frontend-pwa/scripts/audit-utils.test.mjs retired-endpoint fallback and related test scaffolding.
  • leynos/corbusier#79 — Similar Makefile/CI audit restructuring and cargo-audit installation workflow.
  • leynos/shared-actions#271 — Related pinned setup-rust / cargo-binstall version changes that align with CI updates here.

Poem

🦀 Install the bins, run audits both near and far,
Split Node and Rust, pin the versions where they are.
Map packages, normalise advisories in kind,
Report the unexpected, keep allowlists aligned.
Tests assert the plan; docs record the guard.


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (5 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Developer Documentation ⚠️ Warning policyIo adapter signature undocumented; CARGO_AUDIT_IGNORES rationale only in Makefile comment, not in user-facing docs. Document policyIo signature (error, exit methods) in developers-guide.md. Document RUSTSEC-2023-0071 SQLx MySQL rationale in repository-structure.md or developers-guide.md.
Testing (Unit And Behavioural) ⚠️ Warning Makefile tests use only dry-run verification of command strings; no end-to-end tests for validate-audit.js workflow; missing behavioural tests verifying actual audit execution and failure paths. Add tests for validate-audit.js orchestration (assertValidSchema, assertMitigated) with real/mock advisories. Add behavioural tests that execute Makefile targets with actual tool behaviour rather than dry-run checks.
Testing (Compile-Time / Ui) ⚠️ Warning Snapshot tests for advisory reporting are well-designed; end-to-end snapshot tests for validate-audit.js error output are missing despite PR recommendation. Add snapshot tests for validate-audit.js error paths: schema validation errors, unexpected advisories message, and validator vulnerability detection errors.
Domain Architecture ⚠️ Warning Domain logic in assertMitigated couples a policy decision (checking for unexpected advisories) to infrastructure I/O (reportUnexpectedAdvisories side effects), violating domain-adapter boundaries. Extract reportUnexpectedAdvisories call from assertMitigated domain logic; invoke it separately in validate-audit.js after domain validation completes, using injected reportingIo if testability is required.
Observability ⚠️ Warning Audit pipeline lacks logging at decision points and metrics. Only basic stderr error messages are logged; no instrumentation for outcomes, timing, fallback activations, or advisory partitioning. Add structured logging to audit operations: log normal path vs. fallback, endpoints, timeouts, advisory counts, partitioning results with contextual fields like operation, endpoint, timeout_ms, advisory_count, unexpected_count.
Testing (Overall) ❓ Inconclusive No result was produced after verification. Marking as INCONCLUSIVE. Re-run the check or adjust instructions to produce a final result.
✅ Passed checks (14 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add Rust dependency audit to Makefile' accurately describes the main change in the pull request: extending the audit gate to include Rust dependencies. It is specific, relevant, and relates directly to the primary objective of the changeset.
Description check ✅ Passed The pull request description is comprehensive and directly related to the changeset. It provides a clear summary of objectives, a detailed review walkthrough, validation results, and notes explaining the audit-violation fixes and scoped ignores.
Docstring Coverage ✅ Passed Docstring coverage is 86.96% which is sufficient. The required threshold is 80.00%.
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.
User-Facing Documentation ✅ Passed PR contains only developer-facing changes (CI/CD, Makefile, dependencies, dev docs, tests). No user-facing functionality modified. No docs/users-guide.md exists for application users.
Module-Level Documentation ✅ Passed All nine new/modified modules include @file docstrings documenting purpose, utility, function, and component relationships as required.
Testing (Property / Proof) ✅ Passed PR adds property-based tests (fast-check) for critical invariants: version filtering, GHSA deduplication, advisory partitioning, expiry validation, and async abort handling.
Unit Architecture ✅ Passed Pure queries separated from commands with visible side-effects; all I/O through injectable adapters; single module responsibilities; tests verify boundaries with mocks.
Security And Privacy ✅ Passed No secrets, injection risks, or sensitive data exposure. Commands parameterised; inputs validated; permissions restricted; no credentials in logs or errors.
Performance And Resource Use ✅ Passed Resource allocation bounded; timeouts enforced (30s with abort); linear algorithms; I/O properly batched; no nested loops; dependency bumps are maintenance only.
Concurrency And State ✅ Passed Concurrency model is explicit with isolated async operations, no shared mutable state, try-finally resource cleanup, and property-based testing of timeout scenarios.
Architectural Complexity And Maintainability ✅ Passed Module split isolates concerns without cycles. Adapters enable testability; production uses defaults. Makefile reuses ensure_tool macro. Proportionate complexity.
Rust Compiler Lint Integrity ✅ Passed All Rust changes use narrowly-scoped #[expect(...)] attributes with reason strings linked to roadmap #360; no artificial references or module-level suppressions introduced.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cargo-audit-to-makefile

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

codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

leynos added 3 commits May 20, 2026 21:57
Split the audit target into frontend and Rust phases, and run
`cargo audit` against the workspace lockfile. Install `cargo-audit`
in CI before the audit gate so the target is available on runners.

Update vulnerable frontend and Rust dependencies to patched releases.
Keep the SQLx optional MySQL RSA advisory ignored because this
workspace only enables PostgreSQL and RustSec has no fixed RSA release.
Point the CI Rust setup action at the current `leynos/shared-actions`
default-branch commit so the workflow uses the latest shared action.
Restore the `openapi-dump` and `er-snapshots` binary entries that were
collapsed into duplicate `ingest-osm` targets during conflict resolution.
Keep the rebased manifest aligned with `origin/main` while preserving the
audit branch changes.
@lodyai lodyai Bot force-pushed the feat/cargo-audit-to-makefile branch from beeeb98 to 1a63868 Compare May 20, 2026 20:06
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos leynos marked this pull request as ready for review May 21, 2026 20:20
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 21, 2026

Reviewer's Guide

Adds a Rust dependency audit phase to the repository’s audit gate, wires it into CI, and updates Rust and frontend dependency versions to clear actionable vulnerabilities while documenting the new behavior.

Flow diagram for updated make audit target with Rust dependency auditing

flowchart LR
    actor_CI[CI or developer]
    actor_CI --> make_audit[make audit]

    make_audit --> audit_node[audit-node: pnpm -r install && pnpm -r run audit && pnpm run audit:validate]
    make_audit --> rust_audit[rust-audit: cargo audit --file Cargo.lock --ignore RUSTSEC-2023-0071]

    audit_node --> frontend_deps[Frontend dependencies audited]
    rust_audit --> rust_deps[Rust dependencies audited]
Loading

File-Level Changes

Change Details Files
Split the audit Makefile target into separate frontend and Rust phases and configure cargo-audit behavior.
  • Introduce CARGO variable and CARGO_AUDIT_IGNORES flag in the Makefile and extend PATH for cargo binaries.
  • Mark audit, audit-node, and rust-audit as PHONY targets and make audit depend on audit-node and rust-audit.
  • Retain the existing pnpm-based frontend audit under audit-node and add a rust-audit target that runs cargo audit against Cargo.lock with a scoped ignore for RUSTSEC-2023-0071.
Makefile
Document the updated audit workflow for operators.
  • Update repository-structure documentation to describe make audit as running both frontend and Rust audits.
  • Clarify that the frontend audit validates the exception allowlist and that the Rust audit runs cargo audit on the root Cargo.lock while preserving Corepack guidance.
docs/repository-structure.md
Refresh Node dev tooling dependencies and overrides to satisfy the updated audit gate.
  • Bump @mermaid-js/mermaid-cli, ajv, and markdownlint-cli devDependency versions.
  • Align the ajv override to the new version and keep other security-related overrides (fast-uri, glob, js-yaml, lodash, ws via lockfile) intact.
package.json
pnpm-lock.yaml
Update Rust backend dependencies to non-vulnerable versions.
  • Bump diesel, diesel-async, and diesel_migrations to newer minor versions compatible with the existing feature flags.
  • Regenerate Cargo.lock to reflect updated Rust dependency graph and resolve audit violations.
backend/Cargo.toml
Cargo.lock
Extend CI to support Rust auditing and align with the shared Rust setup action pin.
  • Update the leynos/shared-actions setup-rust action reference to a newer commit.
  • Install cargo-audit in the CI job via cargo binstall before running the audit stage so make audit exercises both frontend and Rust audits.
.github/workflows/ci.yml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

sourcery-ai[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

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

🤖 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/ci.yml:
- Around line 94-95: Update the "Install cargo-audit" CI step so it installs a
fixed release instead of the latest; replace the current command string "cargo
binstall --no-confirm cargo-audit" with one that pins the package to version
0.22.1 (e.g., using the cargo-binstall package@version form) so the CI
consistently installs cargo-audit@0.22.1.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 379d987d-38f8-44c5-b9ed-2fb95f4fd2c4

📥 Commits

Reviewing files that changed from the base of the PR and between b23476f and 1a63868.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • .github/workflows/ci.yml
  • Makefile
  • backend/Cargo.toml
  • docs/repository-structure.md
  • package.json

Comment thread .github/workflows/ci.yml Outdated
leynos added 2 commits May 23, 2026 14:06
Add `make audit` to the documented quality gates and note that the
local setup expects Corepack to enable `pnpm`. This keeps the developer
guide aligned with the repository-structure guidance.
Remove the redundant node audit install, add an explicit `cargo-audit`
availability check, and pin the CI install to `cargo-audit@0.22.1`.

Thread audit I/O and expiry-date dependencies through the audit helpers so
fallible process and network work is explicit at the boundary. Add required
`#[expect]` reasons and roadmap links for still-valid lint suppressions.

Update the `qs` override to `6.15.2` and refresh the pnpm lockfile to clear
the current `GHSA-q8mj-m7cp-5q26` audit violation.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 23, 2026

@coderabbitai Please investigate the cause of the following issue using codegraph exploration and research, identify a fix and provide an AI coding agent prompt for the fix:

        PASS [   0.006s] ( 675/1105) backend::diesel_login_users_adapters support::embedded_postgres::tests::setup_apalis_storage_is_linked
 TERMINATING [> 60.000s] (─────────) backend::diesel_login_users_adapters db_present_mode_supports_login_and_users_with_stable_contracts
 TERMINATING [> 60.000s] (─────────) backend::diesel_login_users_adapters db_present_mode_handles_users_table_loss_with_stable_outcomes
     TIMEOUT [  60.003s] ( 676/1105) backend::diesel_login_users_adapters db_present_mode_supports_login_and_users_with_stable_contracts
  stdout ───

    running 1 test

    (test timed out)

  Cancelling due to test failure: 3 tests still running
     TIMEOUT [  60.003s] ( 677/1105) backend::diesel_login_users_adapters db_present_mode_handles_users_table_loss_with_stable_outcomes
  stdout ───

    running 1 test

    (test timed out)

 TERMINATING [> 60.000s] (─────────) backend::diesel_login_users_adapters startup_modes_reject_invalid_credentials_with_unauthorised_envelope::case_2
     TIMEOUT [  60.002s] ( 678/1105) backend::diesel_login_users_adapters startup_modes_reject_invalid_credentials_with_unauthorised_envelope::case_2
  stdout ───

    running 1 test

    (test timed out)

        FAIL [ 169.168s] ( 679/1105) backend::catalogue_descriptor_ingestion_bdd catalogue_and_descriptor_ingestion_supports_success_failure_and_nullable_edge_cases
  stdout ───

    running 1 test
    test catalogue_and_descriptor_ingestion_supports_success_failure_and_nullable_edge_cases has been running for over 60 seconds
    test catalogue_and_descriptor_ingestion_supports_success_failure_and_nullable_edge_cases ... FAILED

    failures:

    failures:
        catalogue_and_descriptor_ingestion_supports_success_failure_and_nullable_edge_cases

    test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 8 filtered out; finished in 169.16s
    
  stderr ───
    The application panicked (crashed).
    Message:  Test cluster setup failed: shared cluster initialisation previously failed: BootstrapError { kind: Other, report: 
       0: bootstrap failed: BootstrapError { kind: Other, report: 
             0: postgresql_embedded::setup() failed
             1: error decoding response body

          Location:
             /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pg-embed-setup-unpriv-0.5.0/src/cluster/worker_invoker/mod.rs:324

            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
             1: <color_eyre[8a036c914ad27c05]::config::EyreHook>::into_eyre_hook::{closure#0}<unknown>
                at <unknown source file>:<unknown line>
             2: eyre[ade532eb8244d9bf]::capture_handler<unknown>
                at <unknown source file>:<unknown line>
             3: <eyre[ade532eb8244d9bf]::Report>::from_msg::<&str, postgresql_embedded[b4d2603bee94b72]::error::Error><unknown>
                at <unknown source file>:<unknown line>
             4: <pg_embedded_setup_unpriv[300f00fc572c2aec]::cluster::worker_invoker::WorkerInvoker>::invoke::<pg_embedded_setup_unpriv[300f00fc572c2aec]::cluster::startup::invoke_lifecycle::{closure#0}><unknown>
                at <unknown source file>:<unknown line>
             5: <pg_embedded_setup_unpriv[300f00fc572c2aec]::cluster::TestCluster>::new_split<unknown>
                at <unknown source file>:<unknown line>
             6: pg_embedded_setup_unpriv[300f00fc572c2aec]::test_support::shared_singleton::shared_cluster_handle<unknown>
                at <unknown source file>:<unknown line>
             7: catalogue_descriptor_ingestion_bdd[d2d6c55bdc757b91]::support::atexit_cleanup::shared_cluster_handle<unknown>
                at <unknown source file>:<unknown line>
             8: <catalogue_descriptor_ingestion_bdd[d2d6c55bdc757b91]::catalogue_and_descriptor_ingestion_supports_success_failure_and_nullable_edge_cases::{closure#0} as core[274c285622937fcf]::ops::function::FnOnce<()>>::call_once<unknown>
                at <unknown source file>:<unknown line>
             9: <fn() -> core[274c285622937fcf]::result::Result<(), alloc[58d6849b0d6b715d]::string::String> as core[274c285622937fcf]::ops::function::FnOnce<()>>::call_once<unknown>
                at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/core/src/ops/function.rs:250
            10: test[22843e112f4c7c90]::__rust_begin_short_backtrace::<core[274c285622937fcf]::result::Result<(), alloc[58d6849b0d6b715d]::string::String>, fn() -> core[274c285622937fcf]::result::Result<(), alloc[58d6849b0d6b715d]::string::String>><unknown>
                at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/test/src/lib.rs:724
            11: test[22843e112f4c7c90]::run_test_in_process::{closure#0}<unknown>
          at <unknown source file>:<unknown line>
       2: <color_eyre[8a036c914ad27c05]::config::PanicHook>::into_panic_hook::{closure#0}<unknown>
          at <unknown source file>:<unknown line>
       3: <alloc[58d6849b0d6b715d]::boxed::Box<dyn for<'a, 'b> core[274c285622937fcf]::ops::function::Fn<(&'a std[123cabe7bf2a605c]::panic::PanicHookInfo<'b>,), Output = ()> + core[274c285622937fcf]::marker::Sync + core[274c285622937fcf]::marker::Send> as core[274c285622937fcf]::ops::function::Fn<(&std[123cabe7bf2a605c]::panic::PanicHookInfo,)>>::call<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/alloc/src/boxed.rs:2289
       4: std[123cabe7bf2a605c]::panicking::panic_with_hook<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/panicking.rs:833
       5: std[123cabe7bf2a605c]::panicking::panic_handler::{closure#0}<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/panicking.rs:698
       6: std[123cabe7bf2a605c]::sys::backtrace::__rust_end_short_backtrace::<std[123cabe7bf2a605c]::panicking::panic_handler::{closure#0}, !><unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/sys/backtrace.rs:182
       7: __rustc[27fdca0b0050a95b]::rust_begin_unwind<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/panicking.rs:689
       8: core[274c285622937fcf]::panicking::panic_fmt<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/core/src/panicking.rs:80
       9: catalogue_descriptor_ingestion_bdd[d2d6c55bdc757b91]::support::cluster_skip::handle_cluster_setup_failure::<(), &alloc[58d6849b0d6b715d]::string::String><unknown>
          at <unknown source file>:<unknown line>
      10: <catalogue_descriptor_ingestion_bdd[d2d6c55bdc757b91]::catalogue_and_descriptor_ingestion_supports_success_failure_and_nullable_edge_cases::{closure#0} as core[274c285622937fcf]::ops::function::FnOnce<()>>::call_once<unknown>
          at <unknown source file>:<unknown line>
      11: <fn() -> core[274c285622937fcf]::result::Result<(), alloc[58d6849b0d6b715d]::string::String> as core[274c285622937fcf]::ops::function::FnOnce<()>>::call_once<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/core/src/ops/function.rs:250
      12: test[22843e112f4c7c90]::__rust_begin_short_backtrace::<core[274c285622937fcf]::result::Result<(), alloc[58d6849b0d6b715d]::string::String>, fn() -> core[274c285622937fcf]::result::Result<(), alloc[58d6849b0d6b715d]::string::String>><unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/test/src/lib.rs:724
      13: test[22843e112f4c7c90]::run_test_in_process::{closure#0}<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/test/src/lib.rs:747
      14: <core[274c285622937fcf]::panic::unwind_safe::AssertUnwindSafe<test[22843e112f4c7c90]::run_test_in_process::{closure#0}> as core[274c285622937fcf]::ops::function::FnOnce<()>>::call_once<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/core/src/panic/unwind_safe.rs:275
      15: std[123cabe7bf2a605c]::panicking::catch_unwind::do_call::<core[274c285622937fcf]::panic::unwind_safe::AssertUnwindSafe<test[22843e112f4c7c90]::run_test_in_process::{closure#0}>, core[274c285622937fcf]::result::Result<(), alloc[58d6849b0d6b715d]::string::String>><unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/panicking.rs:581
      16: std[123cabe7bf2a605c]::panicking::catch_unwind::<core[274c285622937fcf]::result::Result<(), alloc[58d6849b0d6b715d]::string::String>, core[274c285622937fcf]::panic::unwind_safe::AssertUnwindSafe<test[22843e112f4c7c90]::run_test_in_process::{closure#0}>><unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/panicking.rs:544
      17: std[123cabe7bf2a605c]::panic::catch_unwind::<core[274c285622937fcf]::panic::unwind_safe::AssertUnwindSafe<test[22843e112f4c7c90]::run_test_in_process::{closure#0}>, core[274c285622937fcf]::result::Result<(), alloc[58d6849b0d6b715d]::string::String>><unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/panic.rs:359
      18: test[22843e112f4c7c90]::run_test_in_process<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/test/src/lib.rs:747
      19: test[22843e112f4c7c90]::run_test::{closure#0}<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/test/src/lib.rs:668
      20: test[22843e112f4c7c90]::run_test::{closure#1}<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/test/src/lib.rs:698
      21: std[123cabe7bf2a605c]::sys::backtrace::__rust_begin_short_backtrace::<test[22843e112f4c7c90]::run_test::{closure#1}, ()><unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/sys/backtrace.rs:166
      22: std[123cabe7bf2a605c]::thread::lifecycle::spawn_unchecked::<test[22843e112f4c7c90]::run_test::{closure#1}, ()>::{closure#1}::{closure#0}<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/thread/lifecycle.rs:70
      23: <core[274c285622937fcf]::panic::unwind_safe::AssertUnwindSafe<std[123cabe7bf2a605c]::thread::lifecycle::spawn_unchecked<test[22843e112f4c7c90]::run_test::{closure#1}, ()>::{closure#1}::{closure#0}> as core[274c285622937fcf]::ops::function::FnOnce<()>>::call_once<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/core/src/panic/unwind_safe.rs:275
      24: std[123cabe7bf2a605c]::panicking::catch_unwind::do_call::<core[274c285622937fcf]::panic::unwind_safe::AssertUnwindSafe<std[123cabe7bf2a605c]::thread::lifecycle::spawn_unchecked<test[22843e112f4c7c90]::run_test::{closure#1}, ()>::{closure#1}::{closure#0}>, ()><unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/panicking.rs:581
      25: std[123cabe7bf2a605c]::panicking::catch_unwind::<(), core[274c285622937fcf]::panic::unwind_safe::AssertUnwindSafe<std[123cabe7bf2a605c]::thread::lifecycle::spawn_unchecked<test[22843e112f4c7c90]::run_test::{closure#1}, ()>::{closure#1}::{closure#0}>><unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/panicking.rs:544
      26: std[123cabe7bf2a605c]::panic::catch_unwind::<core[274c285622937fcf]::panic::unwind_safe::AssertUnwindSafe<std[123cabe7bf2a605c]::thread::lifecycle::spawn_unchecked<test[22843e112f4c7c90]::run_test::{closure#1}, ()>::{closure#1}::{closure#0}>, ()><unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/panic.rs:359
      27: std[123cabe7bf2a605c]::thread::lifecycle::spawn_unchecked::<test[22843e112f4c7c90]::run_test::{closure#1}, ()>::{closure#1}<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/thread/lifecycle.rs:68
      28: <std[123cabe7bf2a605c]::thread::lifecycle::spawn_unchecked<test[22843e112f4c7c90]::run_test::{closure#1}, ()>::{closure#1} as core[274c285622937fcf]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/core/src/ops/function.rs:250
      29: <alloc[58d6849b0d6b715d]::boxed::Box<dyn core[274c285622937fcf]::ops::function::FnOnce<(), Output = ()> + core[274c285622937fcf]::marker::Send> as core[274c285622937fcf]::ops::function::FnOnce<()>>::call_once<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/alloc/src/boxed.rs:2275
      30: <std[123cabe7bf2a605c]::sys::thread::unix::Thread>::new::thread_start<unknown>
          at /rustc/54333ff079780f803f65dcee30c544050b35f544/library/std/src/sys/thread/unix.rs:118

    Run with COLORBT_SHOW_HIDDEN=1 environment variable to disable frame filtering.
    Run with RUST_BACKTRACE=full to include source snippets.

────────────
     Summary [ 169.538s] 679/1105 tests run: 675 passed, 1 failed, 3 timed out, 4 skipped
     TIMEOUT [  60.003s] ( 676/1105) backend::diesel_login_users_adapters db_present_mode_supports_login_and_users_with_stable_contracts
     TIMEOUT [  60.003s] ( 677/1105) backend::diesel_login_users_adapters db_present_mode_handles_users_table_loss_with_stable_outcomes
     TIMEOUT [  60.002s] ( 678/1105) backend::diesel_login_users_adapters startup_modes_reject_invalid_credentials_with_unauthorised_envelope::case_2
        FAIL [ 169.168s] ( 679/1105) backend::catalogue_descriptor_ingestion_bdd catalogue_and_descriptor_ingestion_supports_success_failure_and_nullable_edge_cases
warning: 426/1105 tests were not run due to test failure (run with --no-fail-fast to run all tests, or run with --max-fail)

Document that `make audit` covers both frontend and Rust dependency
checks, and note the `cargo-audit` prerequisite alongside Corepack so the
local setup matches the Makefile and CI flow.
@coderabbitai

This comment was marked as resolved.

Add root Vitest coverage for the `rust-audit` target, including the
`cargo-audit` availability guard, command shape, and configured RustSec
ignore.

Run architecture linting in CI and tighten the remaining lint expectation
reasons with concrete roadmap references.
codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

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

Caution

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

⚠️ Outside diff range comments (1)
security/audit-utils.js (1)

1-416: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Decompose this module to comply with the 400-line limit.

The file is 416 lines, exceeding the 400-line maximum. Extract one of the following into a dedicated module:

  • Advisory normalisation helpers (deriveAdvisoryKey, normalizeBulkAdvisories, addPackageAdvisories, lines 195–265).
  • Reporting utilities (formatAdvisoryLine, reportUnexpectedAdvisories, partitionAdvisoriesById, lines 362–415).

As per coding guidelines: "No single code file may be longer than 400 lines; long switch statements or dispatch tables should be broken up by feature, and large test data blocks moved to external files."

🤖 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 `@docs/developers-guide.md`:
- Line 26: The repository-wide commit-gates list in the developers guide is
missing `make audit`; update the "commit-gates" list (the section that lists
required commands for commits) to include `make audit` alongside the existing
entries so the guide and other quality-gate lists are synchronized; ensure the
entry is added in the same format as the other commands in that list.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 78fadc3e-0258-4fd5-b9a3-e0f430f775de

📥 Commits

Reviewing files that changed from the base of the PR and between 1a63868 and 3cf72f3.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • .github/workflows/ci.yml
  • Makefile
  • backend/src/inbound/http/schemas.rs
  • backend/src/outbound/persistence/models.rs
  • backend/tests/example_data_runs_bdd.rs
  • docs/developers-guide.md
  • package.json
  • scripts/makefile-audit.test.mjs
  • security/audit-utils.js
  • security/validate-audit.js

Comment thread docs/developers-guide.md
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 24, 2026

@coderabbitai Have the following now been resolved?

  • In the Makefile, audit audit-node rust-audit are declared as .PHONY twice; you can drop the second .PHONY line to avoid redundancy.
  • Consider using the existing ensure_tool helper (or similar check) for cargo-audit in the rust-audit target so local runs fail with a clear message if the tool is missing, instead of relying solely on CI installation.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 24, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read the full Makefile to check .PHONY declarations and rust-audit target
cat Makefile

Length of output: 8603


@leynos — neither issue has been resolved yet.

1. Duplicate .PHONY declaration — the consolidated declaration near the top of the file already contains audit audit-node rust-audit, but the standalone line immediately below it remains:

.PHONY: all clean be fe … audit audit-node rust-audit \
        lint-rust … workspace-sync
.PHONY: audit audit-node rust-audit   ← remove this line

2. ensure_tool not used in rust-audit — the target rolls its own inline check instead of calling the ensure_tool macro that is already defined and used elsewhere in the file:

# Current (inline check)
rust-audit:
	`@command` -v cargo-audit >/dev/null 2>&1 || { echo "Error: cargo-audit is required. Install it with 'cargo binstall --no-confirm cargo-audit@0.22.1'."; exit 1; }
	$(CARGO) audit --file Cargo.lock $(CARGO_AUDIT_IGNORES)

# Fix: use the existing macro, keep the install hint in a comment
rust-audit:
	$(call ensure_tool,cargo-audit)
	# RUSTSEC-2023-0071 is in SQLx's optional MySQL support; this workspace only enables PostgreSQL.
	# Install cargo-audit with: cargo binstall --no-confirm cargo-audit@0.22.1
	$(CARGO) audit --file Cargo.lock $(CARGO_AUDIT_IGNORES)

Remove the duplicate .PHONY line and replace the inline guard with $(call ensure_tool,cargo-audit).

Bump `pg-embed-setup-unpriv` to `0.5.1` and refresh `Cargo.lock`
so the worker subprocess receives the parent environment in CI. Pin the
embedded PostgreSQL runtime version in the Rust test environment to avoid
release-listing requests during archive resolution.

Extract audit reporting helpers from `security/audit-utils.js` so the
shared audit utility module stays below the repository file-size limit.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 24, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

security/audit-utils.js

Comment on file

import { execFileSync, spawnSync } from 'node:child_process';

export {

❌ New issue: Overall Code Complexity
This module has a mean cyclomatic complexity of 4.27 across 22 functions. The mean complexity threshold is 4

@coderabbitai

This comment was marked as resolved.

Add `make audit` to the remaining developer-guide commit-gate
references so the required command lists match the repository-wide
quality gate set.
@coderabbitai

This comment was marked as resolved.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 25, 2026

@coderabbitai please create a new GitHub issue for the following:

Issue 1 — Rust Compiler Lint Integrity

Track removal of #[expect(dead_code)] suppressions on RouteRow, ExampleDataRunRow, UserRow.updated_at, and WalkSessionRow.created_at/updated_at when the corresponding docs/backend-roadmap.md 3.5.1 items are implemented. The suppressions are correctly using #[expect] (which auto-fails when no longer needed), so no action is required now — this issue simply ensures they are removed when the roadmap items land.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh issue create \
  --repo leynos/wildside \
  --title "Remove #[expect(dead_code)] suppressions once roadmap item 3.5.1 lands" \
  --assignee leynos \
  --body "## Summary

Track and remove \`#[expect(dead_code)]\` suppressions on the following items once the corresponding \`docs/backend-roadmap.md 3.5.1\` work is implemented:

- \`RouteRow\`
- \`ExampleDataRunRow\`
- \`UserRow.updated_at\`
- \`WalkSessionRow.created_at\` and \`WalkSessionRow.updated_at\`

## Context

The suppressions are correctly using \`#[expect(dead_code)]\` (which will cause a compile error automatically once the suppressed item is used), so no action is required before the roadmap items land. This issue exists solely to ensure clean-up is not forgotten when roadmap item 3.5.1 is implemented.

Raised during review of PR `#354` by `@leynos`."

Length of output: 924



@leynos — issue created: #360

#360 — Remove #[expect(dead_code)] suppressions once roadmap item 3.5.1 lands has been opened and assigned to you. No action is required now — the #[expect] attributes will automatically trigger a compile error once the suppressed items are put to use, at which point this issue serves as the clean-up prompt.

Document audit exception policy responsibilities, route advisory reporting
through an injected IO adapter, cover bulk-advisory abort cleanup, and reuse
the shared Makefile tool guard for cargo-audit.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 26, 2026

@coderabbitai please provide an AI agent prompt for addition of a reference to #360 to relevant expectation reasons in the code

@coderabbitai

This comment was marked as resolved.

Add the tracked GitHub issue to the roadmap 3.5.1 dead-code
expectations for generated schema and persistence timestamp fields.
Keep the cleanup obligation traceable from the source without changing
runtime behaviour.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 26, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

✅ Actions performed

Review triggered.

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.

Copy link
Copy Markdown
Contributor

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

🤖 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 `@scripts/security-audit-helpers.test.mjs`:
- Around line 451-455: The test is swallowing all exceptions from runAuditJson
which hides regressions; update the property test to assert behavior based on
shouldAbort: when shouldAbort is true, assert runAuditJson(auditIo) rejects with
a timeout error matching /Bulk advisory audit timed out after \d+ms at/; when
shouldAbort is false, assert runAuditJson(auditIo) resolves and returns an
object with status: 0 (use expect(...).rejects.toThrow(...) and
expect(...).resolves.toMatchObject(...) respectively) instead of the empty
try/catch around runAuditJson.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9e1933f1-d453-403f-8915-2634b4bc790a

📥 Commits

Reviewing files that changed from the base of the PR and between ef395da and af495b3.

📒 Files selected for processing (8)
  • Makefile
  • backend/src/inbound/http/schemas.rs
  • backend/src/outbound/persistence/models.rs
  • scripts/makefile-audit.test.mjs
  • scripts/security-audit-helpers.test.mjs
  • scripts/security-audit-reporting.test.mjs
  • security/audit-exception-policy.js
  • security/audit-reporting.js

Comment thread scripts/security-audit-helpers.test.mjs Outdated
Replace the catch-all in the bulk advisory timeout property test with
explicit expectations for each generated case. The aborting path must reject
with the timeout message, while the successful path must resolve with a clean
audit status.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 26, 2026

@coderabbitai Have the following failed checks now been resolved?

If further work is required, please provide an AI agent prompt for the remaining work to be done to address these failures.

Do not treat warnings as optional or aspirational. Where a change is out of scope for this PR, propose a GitHub issue unless one exists already.

❌ Failed checks (1 error, 5 warnings)

Check name Status Explanation Resolution
Testing (Overall) ❌ Error validate-audit.js is untested; reportUnexpectedAdvisories empty-input test is vacuous (checks only mocks); Makefile tests use weak string matching rather than structural assertions. Add integration tests for validate-audit.js workflow; strengthen reportUnexpectedAdvisories tests; add ordering assertions to Makefile tests for cargo-audit check before invocation.
Developer Documentation ⚠️ Warning Docs for reportUnexpectedAdvisories omit the reportingIo adapter parameter. Signature shows (unexpected, heading) but code has (unexpected, heading, reportingIo = defaultReportingIo). Add reportingIo parameter to reportUnexpectedAdvisories documentation in developers-guide.md to match actual signature and existing adapter pattern.
Testing (Unit And Behavioural) ⚠️ Warning Unit tests adequately cover local behaviour and edge cases. End-to-end tests for validate-audit.js script and the audit workflow observable behaviour are missing. Add E2E tests for validate-audit.js covering schema validation, expiry checks, and advisory mismatches. Add workflow tests verifying audit command exit codes and error outputs.
Testing (Property / Proof) ⚠️ Warning Property tests are included for deduplication/partitioning but missing for parseJsonOutput, loadPackageTrees, and collectInstalledPackageVersions which introduce parsing and traversal invariants. Add fast-check properties for: parseJsonOutput with fc.anyJson(), loadPackageTrees with variable tree structures, and collectInstalledPackageVersions with reordered inputs to verify order-independence.
Observability ⚠️ Warning Audit operations lack structured logging, metrics, tracing, and correlation IDs for production diagnostics; cargo audit output not captured. Add structured logging with operation names; emit latency and timeout metrics; add correlation IDs to bulk-advisory requests; capture and report cargo audit execution details.
Architectural Complexity And Maintainability ⚠️ Warning Four new modules add auditIo adapter injection lacking clear justification. Tests use inline mocks, not vi.mock() patterns used elsewhere. No documented reuse path exists. Justify auditIo injection over vi.mock(). Document reuse plans for new modules or consolidate into audit-utils to reduce abstraction.

@coderabbitai

This comment was marked as resolved.

Update the developer guide to match the current
`reportUnexpectedAdvisories` signature and describe the optional stderr
adapter used by tests.
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 26, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

✅ Actions performed

Review triggered.

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.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented May 26, 2026

@coderabbitai please create new GitHub issues for the following:

Testing (Unit And Behavioural) ⚠️ Warning Makefile tests use only dry-run verification of command strings; no end-to-end tests for validate-audit.js workflow; missing behavioural tests verifying actual audit execution and failure paths. Add tests for validate-audit.js orchestration (assertValidSchema, assertMitigated) with real/mock advisories. Add behavioural tests that execute Makefile targets with actual tool behaviour rather than dry-run checks. Testing (Compile-Time / Ui) ⚠️ Warning Snapshot tests for advisory reporting are well-designed; end-to-end snapshot tests for validate-audit.js error output are missing despite PR recommendation. Add snapshot tests for validate-audit.js error paths: schema validation errors, unexpected advisories message, and validator vulnerability detection errors. Domain Architecture ⚠️ Warning Domain logic in assertMitigated couples a policy decision (checking for unexpected advisories) to infrastructure I/O (reportUnexpectedAdvisories side effects), violating domain-adapter boundaries. Extract reportUnexpectedAdvisories call from assertMitigated domain logic; invoke it separately in validate-audit.js after domain validation completes, using injected reportingIo if testability is required.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh issue create \
  --repo leynos/wildside \
  --title "Add E2E and behavioural tests for validate-audit.js workflow and Makefile audit targets" \
  --assignee leynos \
  --body "## Summary

Makefile audit tests exercise only dry-run command strings; no end-to-end or behavioural tests exist for the \`validate-audit.js\` workflow or for actual Makefile target execution.

## Problems

- \`scripts/makefile-audit.test.mjs\` verifies only that expected command strings appear in \`make --dry-run\` output; it does not execute the targets with real tools.
- \`validate-audit.js\` has no tests that exercise the \`assertValidSchema\` and \`assertMitigated\` orchestration paths with real or mock advisories.
- There are no behavioural tests that verify audit execution failure paths (e.g. unexpected advisory detected, schema validation error).

## Acceptance criteria

- Add integration or behavioural tests for the \`validate-audit.js\` orchestration, covering:
  - \`assertValidSchema\` with valid and invalid exception-ledger JSON.
  - \`assertMitigated\` with a match between advisories and the exception ledger (no error), and with an unmatched advisory (error + non-zero exit).
- Add behavioural tests that execute relevant Makefile targets (\`audit-node\`, \`rust-audit\`) with actual (or suitably shimmed) tool behaviour rather than dry-run string checks.

## Context

Raised during review of PR `#354` by `@leynos`."

echo "---"

gh issue create \
  --repo leynos/wildside \
  --title "Add E2E snapshot tests for validate-audit.js error output paths" \
  --assignee leynos \
  --body "## Summary

Snapshot tests for advisory reporting helpers are well-designed, but end-to-end snapshot tests for \`validate-audit.js\` error output are missing despite the PR recommendation.

## Problems

- No snapshot tests exist for the following error paths in \`validate-audit.js\`:
  - AJV schema validation errors (malformed \`audit-exceptions.json\`).
  - Unexpected advisory detection (\`reportUnexpectedAdvisories\` output).
  - Validator vulnerability detection errors (advisory present in audit but not in exception ledger).

## Acceptance criteria

- Add snapshot tests (using Vitest \`toMatchInlineSnapshot\` or \`toMatchSnapshot\`) for \`validate-audit.js\` error paths, covering at minimum:
  - Schema validation failure output.
  - Unexpected-advisory heading and bullet-line output.
  - At least one end-to-end path that drives \`validate-audit.js\` from a controlled advisory fixture through to the final error message captured from \`reportingIo\`.

## Context

Raised during review of PR `#354` by `@leynos`."

echo "---"

gh issue create \
  --repo leynos/wildside \
  --title "Decouple assertMitigated domain logic from reportUnexpectedAdvisories I/O side effects" \
  --assignee leynos \
  --body "## Summary

\`assertMitigated\` in \`validate-audit.js\` couples a pure policy decision (determining whether unexpected advisories exist) to infrastructure I/O (\`reportUnexpectedAdvisories\` side effects), violating domain-adapter boundaries already established by the \`policyIo\` pattern in \`audit-exception-policy.js\`.

## Problem

Calling \`reportUnexpectedAdvisories\` directly inside \`assertMitigated\` means:
- The domain function cannot be tested without either suppressing or capturing \`console.error\` output.
- The reporting transport is baked into domain logic rather than injected at the call site.
- The pattern is inconsistent with \`assertNoExpired\`, which accepts a \`policyIo\` adapter.

## Acceptance criteria

- Extract the \`reportUnexpectedAdvisories\` call out of \`assertMitigated\`.
- \`assertMitigated\` should return (or expose) the partition result rather than performing I/O.
- \`validate-audit.js\` invokes \`reportUnexpectedAdvisories\` after \`assertMitigated\` completes, passing an injected \`reportingIo\` adapter if testability is required.
- Update tests to exercise \`assertMitigated\` independently of I/O, and to exercise the reporting step separately.

## Context

Raised during review of PR `#354` by `@leynos`."

Length of output: 4262



@leynos — all three issues have been created and assigned to you:

@leynos leynos merged commit 0ac3cd5 into main May 26, 2026
4 checks passed
@leynos leynos deleted the feat/cargo-audit-to-makefile branch May 26, 2026 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant