Skip to content

Add optional Rust/Cargo readiness policy - #237

Open
Brian Luby (brianluby) wants to merge 7 commits into
microsoft:mainfrom
brianluby:codex/rust-readiness-policy
Open

Add optional Rust/Cargo readiness policy#237
Brian Luby (brianluby) wants to merge 7 commits into
microsoft:mainfrom
brianluby:codex/rust-readiness-policy

Conversation

@brianluby

Copy link
Copy Markdown

Add an optional Rust/Cargo readiness policy

This adds examples/policies/rust.mjs: a reviewed, opt-in policy module that evaluates pure Rust repositories with Cargo-specific evidence instead of relying on the default language-neutral checks.

For pure Rust repositories, it:

  • Replaces generic lint, format, typecheck, build, test, and lockfile checks with Rust/Cargo equivalents.
  • Adds toolchain-pinning and supply-chain-policy checks.
  • Leaves the existing generic behavior unchanged for mixed Rust/Node repositories, where repo-level evidence cannot be safely attributed to one ecosystem.
  • Uses fixed repository-relative probes, does not execute subprocesses or access the network, and caps Cargo.toml reads at 1 MiB.

Example usage:

cd /path/to/rust-workspace
npx agentrc readiness . \
  --policy /path/to/agentrc/examples/policies/rust.mjs

Example result from a representative Cargo workspace:

# Default policy
Level: 0 (Functional)
Generic lint, build, test, and lockfile checks do not reflect Cargo tooling.

# With rust.mjs
Level: 4 (Optimized)
Cargo build, test, toolchain, lockfile, and supply-chain evidence are recognized.

In this example, the remaining Rust-specific action is intentionally precise:

Missing Rust lint configuration (clippy.toml, .clippy.toml,
or an uncommented [lints] table).

Module policies are trusted executable code, so they must be reviewed and passed explicitly with --policy; they cannot be referenced from agentrc.config.json. Since published packages include dist/ only, consumers should copy a reviewed policy module into their repository for repeatable use.

Copilot AI lite review requested due to automatic review settings July 19, 2026 20:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds an opt-in, reviewed Rust/Cargo readiness policy module (examples/policies/rust.mjs) so pure Rust repositories can be evaluated with Cargo-specific evidence while keeping existing readiness behavior for non-Rust (and mixed) repos. This fits into AgentRC’s readiness policy system by providing a “trusted executable code” policy that must be explicitly passed via --policy.

Changes:

  • Introduces examples/policies/rust.mjs implementing Rust/Cargo-focused replacements for key readiness criteria plus toolchain/supply-chain checks.
  • Adds comprehensive Vitest coverage and fixture repos to validate Rust-policy behavior and security properties (fixed-path probes, symlink rejection, bounded Cargo manifest reads).
  • Updates docs/templates to reflect Node.js 22+ requirements and to document module-policy usage and chaining guidance.

Reviewed changes

Copilot reviewed 39 out of 44 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
vitest.config.ts Broadens Vitest excludes to ignore nested node_modules directories.
src/services/tests/rust-policy.test.ts Adds end-to-end tests covering Rust policy behavior, chaining, and security constraints.
src/services/tests/fixtures/rust-policy/well-tooled-rust/supply-chain/config.toml Fixture evidence for supply-chain policy detection.
src/services/tests/fixtures/rust-policy/well-tooled-rust/rustfmt.toml Fixture evidence for rustfmt configuration detection.
src/services/tests/fixtures/rust-policy/well-tooled-rust/rust-toolchain.toml Fixture evidence for pinned toolchain detection.
src/services/tests/fixtures/rust-policy/well-tooled-rust/README.md Fixture documentation for the “well-tooled” Rust workspace.
src/services/tests/fixtures/rust-policy/well-tooled-rust/LICENSE Fixture license file for repo-health evidence scenarios.
src/services/tests/fixtures/rust-policy/well-tooled-rust/deny.toml Fixture evidence for cargo-deny policy detection.
src/services/tests/fixtures/rust-policy/well-tooled-rust/crates/worker/Cargo.toml Fixture crate manifest for workspace detection.
src/services/tests/fixtures/rust-policy/well-tooled-rust/crates/app/Cargo.toml Fixture crate manifest for workspace detection.
src/services/tests/fixtures/rust-policy/well-tooled-rust/clippy.toml Fixture evidence for clippy configuration detection.
src/services/tests/fixtures/rust-policy/well-tooled-rust/Cargo.toml Fixture workspace manifest including [workspace.lints].
src/services/tests/fixtures/rust-policy/well-tooled-rust/Cargo.lock Fixture lockfile evidence for Cargo lockfile detection.
src/services/tests/fixtures/rust-policy/well-tooled-rust/AGENTS.md Fixture instructions file for readiness/instruction consistency coverage.
src/services/tests/fixtures/rust-policy/well-tooled-rust/.cargo/audit.toml Fixture evidence for cargo-audit configuration detection.
src/services/tests/fixtures/rust-policy/python-only/pyproject.toml Non-Rust fixture ensuring fallback behavior remains stable.
src/services/tests/fixtures/rust-policy/python-only/mypy.ini Non-Rust fixture ensuring fallback behavior remains stable.
src/services/tests/fixtures/rust-policy/node-only/tsconfig.json Node-only fixture for baseline/fallback comparisons.
src/services/tests/fixtures/rust-policy/node-only/package.json Node-only fixture scripts for build/test criteria.
src/services/tests/fixtures/rust-policy/node-only/package-lock.json Node-only fixture lockfile evidence.
src/services/tests/fixtures/rust-policy/node-only/biome.json Node-only fixture lint/format evidence.
src/services/tests/fixtures/rust-policy/node-only/.prettierrc Node-only fixture lint/format evidence.
src/services/tests/fixtures/rust-policy/mixed-rust-node/package.json Mixed fixture used to validate fallback behavior for repo-scoped criteria.
src/services/tests/fixtures/rust-policy/mixed-rust-node/package-lock.json Mixed fixture lockfile evidence for fallback behavior.
src/services/tests/fixtures/rust-policy/mixed-rust-node/Cargo.toml Mixed fixture Rust manifest used to prevent unsafe repo-level attribution.
src/services/tests/fixtures/rust-policy/mixed-rust-node/biome.json Mixed fixture lint/format evidence for fallback behavior.
src/services/tests/fixtures/rust-policy/minimal-rust/Cargo.toml Minimal Rust fixture manifest for pure-Rust detection.
src/services/tests/fixtures/rust-policy/cargo-workspace/crates/worker/Cargo.toml Cargo workspace fixture crate manifest.
src/services/tests/fixtures/rust-policy/cargo-workspace/crates/api/Cargo.toml Cargo workspace fixture crate manifest.
src/services/tests/fixtures/rust-policy/cargo-workspace/Cargo.toml Cargo workspace fixture root manifest.
src/services/tests/fixtures/rust-policy/cargo-workspace/Cargo.lock Cargo workspace fixture lockfile.
README.md Updates stated minimum Node.js version to 22+.
examples/README.md Documents how to run/copy the Rust policy from a source checkout and how to chain policies.
examples/policies/rust.mjs Adds the trusted Rust/Cargo readiness policy implementation.
examples/policies/README.md Documents the Rust readiness policy, constraints, and chaining guidance.
docs/policies.md Clarifies JSON-vs-module policy configuration and documents the Rust policy example.
docs/getting-started.md Updates prerequisites to Node.js 22+.
docs/ci-integration.md Updates runner Node version guidance and CI examples to Node.js 22+.
CONTRIBUTING.md Updates required CI matrix description for tests (Node 22 on Ubuntu/Windows).
AGENTS.md Updates build output note to reflect Node 22+.
.prettierignore Ignores .agents/ integration-managed content.
.gitignore Ignores local agent integration directories and spec artifacts.
.github/PULL_REQUEST_TEMPLATE.md Strengthens PR checklist with explicit command/contract/security checks.
.github/instructions/vscode-extension.instructions.md Updates extension instructions to use the @agentrc/core/* path alias for shared services.
Files not reviewed (2)
  • src/services/tests/fixtures/rust-policy/mixed-rust-node/package-lock.json: Generated file
  • src/services/tests/fixtures/rust-policy/node-only/package-lock.json: Generated file

Comment on lines +195 to +204
const finalStats = await opened.handle.stat({ bigint: true });
if (
totalBytes > MAX_CARGO_MANIFEST_BYTES ||
!finalStats.isFile() ||
finalStats.size > BigInt(MAX_CARGO_MANIFEST_BYTES) ||
!hasSameIdentity(opened.stats, finalStats) ||
!(await hasUnchangedSafePath(opened))
) {
return undefined;
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Created a fix and test for this issue.
428228a

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Copilot please review 428228a

@brianluby

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 39 out of 44 changed files in this pull request and generated 2 comments.

Files not reviewed (2)
  • src/services/tests/fixtures/rust-policy/mixed-rust-node/package-lock.json: Generated file
  • src/services/tests/fixtures/rust-policy/node-only/package-lock.json: Generated file

Comment on lines +300 to +309
async function rustOnlyResult(context, candidates, title) {
if (!(await isRootRustRepository(context))) {
return { status: "skip", reason: "Not a root Rust repository." };
}

const evidence = await firstSafeFixedFile(context.repoPath, candidates);
return evidence
? { status: "pass", evidence: [evidence] }
: { status: "fail", reason: `Missing ${title}.`, evidence: [...candidates] };
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Addressed in 6c8eb68. rustOnlyResult now requires isPureRustRepository, so mixed Rust/Node repositories skip both Rust-only criteria rather than gaining new evidence failures. Added focused test coverage; the Rust-policy suite, format check, and typecheck pass (lint exits 0 with the known import-order warnings).

Comment on lines +436 to +439
for (const id of ["lint-config", "format-config", "typecheck-config", "lockfile"] as const) {
expect(getCriterion(policyReport, id)).toEqual(getCriterion(baseline, id));
}
});

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Addressed in 6c8eb68. The mixed Rust/Node fixture now asserts that rust-toolchain-pinned and rust-supply-chain both skip under the pure-Rust guard, preventing this behavior from regressing. The Rust-policy suite, format check, and typecheck pass (lint exits 0 with the known import-order warnings).

Copilot AI review requested due to automatic review settings July 19, 2026 20:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 39 out of 44 changed files in this pull request and generated no new comments.

Files not reviewed (2)
  • src/services/tests/fixtures/rust-policy/mixed-rust-node/package-lock.json: Generated file
  • src/services/tests/fixtures/rust-policy/node-only/package-lock.json: Generated file

Copilot AI review requested due to automatic review settings August 9, 2026 16:58
@brianluby

Copy link
Copy Markdown
Author

Added follow-up commit 9852809 addressing the post-submission scan findings:

  • documented and tightened the zero-device/inode compatibility fallback
  • added coverage for both O_NOFOLLOW branches
  • removed a redundant filesystem traversal
  • made Rust helpers defensive around missing context
  • aligned generic typecheck candidates and failure evidence

Validation: 711 tests, typecheck, lint, formatting, build, and git diff --check all pass. Ready for another review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 40 out of 45 changed files in this pull request and generated no new comments.

Files not reviewed (2)
  • src/services/tests/fixtures/rust-policy/mixed-rust-node/package-lock.json: Generated file
  • src/services/tests/fixtures/rust-policy/node-only/package-lock.json: Generated file
Suppressed comments (3)

examples/policies/rust.mjs:238

  • isPureRustRepository() currently only checks for a root Cargo.toml plus “no Node scope”. That means repos like Rust+Python (Cargo.toml + pyproject.toml) will be treated as “pure Rust” and have the generic typecheck/build/test/lockfile checks replaced, which doesn’t match the stated “pure Rust repository” intent.

Consider also requiring that the analyzer-reported languages are Rust-only (while still using the safe Cargo.toml probe) so mixed non-Node repos keep the default behavior.

async function isPureRustRepository(context) {
  return (await isRootRustRepository(context)) && !hasNodeScope(context);
}

docs/policies.md:41

  • The docs say the policy performs “at most one 1 MiB-capped Cargo.toml content read”, but rust.mjs allocates/reads up to MAX_CARGO_MANIFEST_BYTES + 1 bytes to fail closed on growth races. The wording should reflect the +1-byte probe so readers aren’t misled about the maximum read size.
fixed repository-relative probes, at most one 1 MiB-capped `Cargo.toml` content read, and no

examples/policies/README.md:60

  • This line says the Cargo.toml content read is “capped at 1 MiB”, but the implementation intentionally reads up to 1 MiB + 1 byte to detect manifests that grow during the bounded read. Updating the wording to mention the +1-byte probe will keep the documentation accurate.
It makes only fixed-path reads, performs at most one `Cargo.toml` content read (capped at 1 MiB),
and rejects symbolic links for its evidence probes. A missing `Cargo.lock` in a pure Rust repository

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